Luracast / Restler

Simple and effective multi-format Web API Server to host your PHP API as Pragmatic REST and/or RESTful API
http://luracast.com/products/restler/
GNU Lesser General Public License v2.1
1.36k stars 315 forks source link

Best practise: Application directory structure #326

Closed letsbyteit closed 10 years ago

letsbyteit commented 10 years ago

Hey guys! Can you please recommend a 'best practise' directory structure for a PHP application using restler? I'm really new to php applications and my structure seems very messy.

Also how a minimal package should look like, for instance I want to keep important files only for fast installation of my application (I need OAuth2, but Twig blows the package up, I think? But your code works fine with a twig template).

My current structure (if you can call it that):

└── API
    ├── Core // here a my API-Classes located
    ├── OAuth2 // the very special oauth thing
    ├── Twig // this twig thing is because of oauth
    ├── cache // restler cache
    ├── explorer // the restler explorer
    ├── log4php // a logging framework
    ├── packages // my folder for packages (plugins, themes)
    └── restler
        ├── bin
        ├── features
        │   ├── bootstrap
        │   ├── examples
        │   ├── restler
        │   └── tests
        │       └── param
        ├── scratch
        ├── vendor
        │   ├── Luracast
        │   │   ├── Restler
        │   │   │   ├── Data
        │   │   │   ├── Filter
        │   │   │   ├── Format
        │   │   │   ├── UI
        │   │   │   ├── compatibility
        │   │   │   └── views
        │   │   ├── _Restler
        │   │   │   ├── Data
        │   │   │   ├── Filter
        │   │   │   └── Format
        │   │   └── explorer
        │   │       └── dist
        │   │           ├── css
        │   │           ├── images
        │   │           └── lib
        │   ├── behat
        │   │   ├── behat
        │   │   │   ├── bin
        │   │   │   ├── chef
        │   │   │   │   └── cookbooks
        │   │   │   │       └── php54
        │   │   │   │           └── recipes
        │   │   │   ├── features
        │   │   │   │   ├── annotations
        │   │   │   │   ├── bootstrap
        │   │   │   │   └── closures
        │   │   │   └── src
        │   │   │       └── Behat
        │   │   │           └── Behat
        │   │   │               ├── Annotation
        │   │   │               ├── Compiler
        │   │   │               ├── Console
        │   │   │               │   ├── Command
        │   │   │               │   ├── Formatter
        │   │   │               │   ├── Input
        │   │   │               │   └── Processor
        │   │   │               ├── Context
        │   │   │               │   ├── ClassGuesser
        │   │   │               │   ├── Initializer
        │   │   │               │   ├── Loader
        │   │   │               │   └── Step
        │   │   │               ├── DataCollector
        │   │   │               ├── Definition
        │   │   │               │   ├── Annotation
        │   │   │               │   ├── Loader
        │   │   │               │   └── Proposal
        │   │   │               ├── DependencyInjection
        │   │   │               │   ├── Compiler
        │   │   │               │   ├── Configuration
        │   │   │               │   └── config
        │   │   │               ├── Event
        │   │   │               ├── Exception
        │   │   │               ├── Extension
        │   │   │               ├── Formatter
        │   │   │               ├── Gherkin
        │   │   │               │   └── Loader
        │   │   │               ├── HelpPrinter
        │   │   │               ├── Hook
        │   │   │               │   ├── Annotation
        │   │   │               │   └── Loader
        │   │   │               ├── Tester
        │   │   │               └── Util
        │   │   │                   └── data
        │   │   └── gherkin
        │   │       ├── bin
        │   │       ├── src
        │   │       │   └── Behat
        │   │       │       └── Gherkin
        │   │       │           ├── Cache
        │   │       │           ├── Dumper
        │   │       │           ├── Exception
        │   │       │           ├── Filter
        │   │       │           ├── Keywords
        │   │       │           ├── Loader
        │   │       │           └── Node
        │   │       └── tests
        │   │           └── Behat
        │   │               └── Gherkin
        │   │                   ├── Cache
        │   │                   ├── Dumper
        │   │                   ├── Filter
        │   │                   ├── Fixtures
        │   │                   │   ├── directories
        │   │                   │   │   └── phps
        │   │                   │   ├── etalons
        │   │                   │   ├── features
        │   │                   │   └── i18n
        │   │                   ├── Keywords
        │   │                   ├── Loader
        │   │                   └── Node
        │   ├── bshaffer
        │   │   └── oauth2-server-php
        │   │       ├── src
        │   │       │   └── OAuth2
        │   │       │       ├── Controller
        │   │       │       ├── GrantType
        │   │       │       ├── Response
        │   │       │       ├── ResponseType
        │   │       │       ├── Storage
        │   │       │       ├── TokenType
        │   │       │       └── Util
        │   │       └── test
        │   │           ├── OAuth2
        │   │           │   ├── GrantType
        │   │           │   ├── Server
        │   │           │   │   ├── Access
        │   │           │   │   ├── Authorize
        │   │           │   │   └── Grant
        │   │           │   └── Storage
        │   │           ├── config
        │   │           └── lib
        │   │               └── OAuth2
        │   │                   ├── Request
        │   │                   └── Storage
        │   ├── composer
        │   ├── guzzle
        │   │   └── guzzle
        │   │       ├── phing
        │   │       │   ├── imports
        │   │       │   └── tasks
        │   │       ├── src
        │   │       │   └── Guzzle
        │   │       │       ├── Batch
        │   │       │       │   └── Exception
        │   │       │       ├── Cache
        │   │       │       ├── Common
        │   │       │       │   └── Exception
        │   │       │       ├── Http
        │   │       │       │   ├── Curl
        │   │       │       │   ├── Exception
        │   │       │       │   ├── Message
        │   │       │       │   └── Resources
        │   │       │       ├── Inflection
        │   │       │       ├── Iterator
        │   │       │       ├── Log
        │   │       │       ├── Parser
        │   │       │       │   ├── Cookie
        │   │       │       │   ├── Message
        │   │       │       │   ├── UriTemplate
        │   │       │       │   └── Url
        │   │       │       ├── Plugin
        │   │       │       │   ├── Async
        │   │       │       │   ├── Backoff
        │   │       │       │   ├── Cache
        │   │       │       │   ├── Cookie
        │   │       │       │   │   ├── CookieJar
        │   │       │       │   │   └── Exception
        │   │       │       │   ├── CurlAuth
        │   │       │       │   ├── History
        │   │       │       │   ├── Log
        │   │       │       │   ├── Md5
        │   │       │       │   ├── Mock
        │   │       │       │   └── Oauth
        │   │       │       ├── Service
        │   │       │       │   ├── Builder
        │   │       │       │   ├── Command
        │   │       │       │   │   ├── Factory
        │   │       │       │   │   └── LocationVisitor
        │   │       │       │   │       ├── Request
        │   │       │       │   │       └── Response
        │   │       │       │   ├── Description
        │   │       │       │   ├── Exception
        │   │       │       │   └── Resource
        │   │       │       └── Stream
        │   │       └── tests
        │   │           └── Guzzle
        │   │               └── Tests
        │   │                   ├── Batch
        │   │                   ├── Cache
        │   │                   ├── Common
        │   │                   │   └── Exception
        │   │                   ├── Http
        │   │                   │   ├── Curl
        │   │                   │   ├── Exception
        │   │                   │   └── Message
        │   │                   ├── Inflection
        │   │                   ├── Iterator
        │   │                   ├── Log
        │   │                   ├── Mock
        │   │                   ├── Parser
        │   │                   │   ├── Cookie
        │   │                   │   ├── Message
        │   │                   │   ├── UriTemplate
        │   │                   │   └── Url
        │   │                   ├── Plugin
        │   │                   │   ├── Async
        │   │                   │   ├── Backoff
        │   │                   │   ├── Cache
        │   │                   │   ├── Cookie
        │   │                   │   │   └── CookieJar
        │   │                   │   ├── CurlAuth
        │   │                   │   ├── History
        │   │                   │   ├── Log
        │   │                   │   ├── Md5
        │   │                   │   ├── Mock
        │   │                   │   └── Oauth
        │   │                   ├── Service
        │   │                   │   ├── Builder
        │   │                   │   ├── Command
        │   │                   │   │   ├── Factory
        │   │                   │   │   └── LocationVisitor
        │   │                   │   │       ├── Request
        │   │                   │   │       └── Response
        │   │                   │   ├── Description
        │   │                   │   ├── Exception
        │   │                   │   ├── Mock
        │   │                   │   │   ├── Command
        │   │                   │   │   │   └── Sub
        │   │                   │   │   └── Model
        │   │                   │   └── Resource
        │   │                   ├── Stream
        │   │                   └── TestData
        │   │                       └── services
        │   ├── mustache
        │   │   └── mustache
        │   │       ├── bin
        │   │       ├── src
        │   │       │   └── Mustache
        │   │       │       ├── Exception
        │   │       │       ├── Loader
        │   │       │       └── Logger
        │   │       ├── test
        │   │       │   ├── Mustache
        │   │       │   │   └── Test
        │   │       │   │       ├── Exception
        │   │       │   │       ├── FiveThree
        │   │       │   │       │   └── Functional
        │   │       │   │       ├── Functional
        │   │       │   │       ├── Loader
        │   │       │   │       └── Logger
        │   │       │   └── fixtures
        │   │       │       ├── autoloader
        │   │       │       │   └── Mustache
        │   │       │       ├── examples
        │   │       │       │   ├── child_context
        │   │       │       │   ├── comments
        │   │       │       │   ├── complex
        │   │       │       │   ├── delimiters
        │   │       │       │   ├── dot_notation
        │   │       │       │   ├── double_section
        │   │       │       │   ├── escaped
        │   │       │       │   ├── grand_parent_context
        │   │       │       │   ├── i18n
        │   │       │       │   ├── implicit_iterator
        │   │       │       │   ├── inverted_double_section
        │   │       │       │   ├── inverted_section
        │   │       │       │   ├── partials
        │   │       │       │   │   └── partials
        │   │       │       │   ├── recursive_partials
        │   │       │       │   │   └── partials
        │   │       │       │   ├── section_iterator_objects
        │   │       │       │   ├── section_magic_objects
        │   │       │       │   ├── section_objects
        │   │       │       │   ├── sections
        │   │       │       │   ├── sections_nested
        │   │       │       │   ├── simple
        │   │       │       │   ├── unescaped
        │   │       │       │   ├── utf8
        │   │       │       │   ├── utf8_unescaped
        │   │       │       │   └── whitespace
        │   │       │       │       └── partials
        │   │       │       └── templates
        │   │       └── vendor
        │   │           ├── spec
        │   │           └── yaml
        │   ├── rodneyrehm
        │   │   └── plist
        │   │       ├── classes
        │   │       │   └── CFPropertyList
        │   │       ├── examples
        │   │       └── tests
        │   ├── symfony
        │   │   ├── config
        │   │   │   └── Symfony
        │   │   │       └── Component
        │   │   │           └── Config
        │   │   │               ├── Definition
        │   │   │               │   ├── Builder
        │   │   │               │   └── Exception
        │   │   │               ├── Exception
        │   │   │               ├── Loader
        │   │   │               ├── Resource
        │   │   │               ├── Tests
        │   │   │               │   ├── Definition
        │   │   │               │   │   └── Builder
        │   │   │               │   ├── Fixtures
        │   │   │               │   │   ├── Again
        │   │   │               │   │   ├── Builder
        │   │   │               │   │   ├── Configuration
        │   │   │               │   │   └── Util
        │   │   │               │   ├── Loader
        │   │   │               │   ├── Resource
        │   │   │               │   └── Util
        │   │   │               └── Util
        │   │   ├── console
        │   │   │   └── Symfony
        │   │   │       └── Component
        │   │   │           └── Console
        │   │   │               ├── Command
        │   │   │               ├── Descriptor
        │   │   │               ├── Event
        │   │   │               ├── Formatter
        │   │   │               ├── Helper
        │   │   │               ├── Input
        │   │   │               ├── Output
        │   │   │               ├── Resources
        │   │   │               │   └── bin
        │   │   │               ├── Tester
        │   │   │               └── Tests
        │   │   │                   ├── Command
        │   │   │                   ├── Descriptor
        │   │   │                   ├── Fixtures
        │   │   │                   ├── Formatter
        │   │   │                   ├── Helper
        │   │   │                   ├── Input
        │   │   │                   ├── Output
        │   │   │                   └── Tester
        │   │   ├── dependency-injection
        │   │   │   └── Symfony
        │   │   │       └── Component
        │   │   │           └── DependencyInjection
        │   │   │               ├── Compiler
        │   │   │               ├── Dumper
        │   │   │               ├── Exception
        │   │   │               ├── Extension
        │   │   │               ├── LazyProxy
        │   │   │               │   ├── Instantiator
        │   │   │               │   └── PhpDumper
        │   │   │               ├── Loader
        │   │   │               │   └── schema
        │   │   │               │       └── dic
        │   │   │               │           └── services
        │   │   │               ├── ParameterBag
        │   │   │               └── Tests
        │   │   │                   ├── Compiler
        │   │   │                   ├── Dumper
        │   │   │                   ├── Extension
        │   │   │                   ├── Fixtures
        │   │   │                   │   ├── containers
        │   │   │                   │   ├── graphviz
        │   │   │                   │   ├── includes
        │   │   │                   │   │   └── schema
        │   │   │                   │   ├── ini
        │   │   │                   │   ├── php
        │   │   │                   │   ├── xml
        │   │   │                   │   │   ├── extension1
        │   │   │                   │   │   ├── extension2
        │   │   │                   │   │   └── extensions
        │   │   │                   │   └── yaml
        │   │   │                   ├── LazyProxy
        │   │   │                   │   ├── Instantiator
        │   │   │                   │   └── PhpDumper
        │   │   │                   ├── Loader
        │   │   │                   └── ParameterBag
        │   │   ├── event-dispatcher
        │   │   │   └── Symfony
        │   │   │       └── Component
        │   │   │           └── EventDispatcher
        │   │   │               ├── Debug
        │   │   │               └── Tests
        │   │   ├── filesystem
        │   │   │   └── Symfony
        │   │   │       └── Component
        │   │   │           └── Filesystem
        │   │   │               ├── Exception
        │   │   │               └── Tests
        │   │   ├── finder
        │   │   │   └── Symfony
        │   │   │       └── Component
        │   │   │           └── Finder
        │   │   │               ├── Adapter
        │   │   │               ├── Comparator
        │   │   │               ├── Exception
        │   │   │               ├── Expression
        │   │   │               ├── Iterator
        │   │   │               ├── Shell
        │   │   │               └── Tests
        │   │   │                   ├── Comparator
        │   │   │                   ├── Expression
        │   │   │                   ├── FakeAdapter
        │   │   │                   ├── Fixtures
        │   │   │                   │   ├── A
        │   │   │                   │   │   └── B
        │   │   │                   │   │       └── C
        │   │   │                   │   ├── copy
        │   │   │                   │   │   └── A
        │   │   │                   │   │       └── B
        │   │   │                   │   │           └── C
        │   │   │                   │   ├── one
        │   │   │                   │   │   └── b
        │   │   │                   │   └── with\ space
        │   │   │                   └── Iterator
        │   │   ├── translation
        │   │   │   └── Symfony
        │   │   │       └── Component
        │   │   │           └── Translation
        │   │   │               ├── Catalogue
        │   │   │               ├── Dumper
        │   │   │               ├── Exception
        │   │   │               ├── Extractor
        │   │   │               ├── Loader
        │   │   │               │   └── schema
        │   │   │               │       └── dic
        │   │   │               │           └── xliff-core
        │   │   │               ├── Tests
        │   │   │               │   ├── Catalogue
        │   │   │               │   ├── Dumper
        │   │   │               │   ├── Loader
        │   │   │               │   └── fixtures
        │   │   │               │       └── resourcebundle
        │   │   │               │           ├── corrupted
        │   │   │               │           ├── dat
        │   │   │               │           └── res
        │   │   │               └── Writer
        │   │   └── yaml
        │   │       └── Symfony
        │   │           └── Component
        │   │               └── Yaml
        │   │                   ├── Exception
        │   │                   └── Tests
        │   │                       └── Fixtures
        │   ├── twig
        │   │   └── twig
        │   │       ├── doc
        │   │       │   ├── filters
        │   │       │   ├── functions
        │   │       │   ├── tags
        │   │       │   └── tests
        │   │       ├── ext
        │   │       │   └── twig
        │   │       ├── lib
        │   │       │   └── Twig
        │   │       │       ├── Error
        │   │       │       ├── Extension
        │   │       │       ├── Filter
        │   │       │       ├── Function
        │   │       │       ├── Loader
        │   │       │       ├── Node
        │   │       │       │   └── Expression
        │   │       │       │       ├── Binary
        │   │       │       │       ├── Filter
        │   │       │       │       ├── Test
        │   │       │       │       └── Unary
        │   │       │       ├── NodeVisitor
        │   │       │       ├── Sandbox
        │   │       │       ├── Test
        │   │       │       └── TokenParser
        │   │       └── test
        │   │           └── Twig
        │   │               └── Tests
        │   │                   ├── Extension
        │   │                   ├── Fixtures
        │   │                   │   ├── errors
        │   │                   │   ├── exceptions
        │   │                   │   ├── expressions
        │   │                   │   ├── filters
        │   │                   │   ├── functions
        │   │                   │   │   └── include
        │   │                   │   ├── macros
        │   │                   │   ├── regression
        │   │                   │   ├── tags
        │   │                   │   │   ├── autoescape
        │   │                   │   │   ├── block
        │   │                   │   │   ├── embed
        │   │                   │   │   ├── filter
        │   │                   │   │   ├── for
        │   │                   │   │   ├── if
        │   │                   │   │   ├── include
        │   │                   │   │   ├── inheritance
        │   │                   │   │   ├── macro
        │   │                   │   │   ├── raw
        │   │                   │   │   ├── sandbox
        │   │                   │   │   ├── set
        │   │                   │   │   ├── spaceless
        │   │                   │   │   ├── use
        │   │                   │   │   └── verbatim
        │   │                   │   └── tests
        │   │                   ├── Loader
        │   │                   │   └── Fixtures
        │   │                   │       ├── named
        │   │                   │       ├── named_bis
        │   │                   │       ├── named_final
        │   │                   │       ├── named_ter
        │   │                   │       ├── normal
        │   │                   │       ├── normal_bis
        │   │                   │       ├── normal_final
        │   │                   │       └── normal_ter
        │   │                   ├── Node
        │   │                   │   └── Expression
        │   │                   │       ├── Binary
        │   │                   │       ├── PHP53
        │   │                   │       └── Unary
        │   │                   └── NodeVisitor
        │   └── zendframework
        │       └── zendamf
        │           ├── library
        │           │   └── ZendAmf
        │           │       ├── Adobe
        │           │       ├── Exception
        │           │       ├── Parser
        │           │       │   ├── Amf0
        │           │       │   ├── Amf3
        │           │       │   ├── Exception
        │           │       │   └── Resource
        │           │       ├── Request
        │           │       ├── Response
        │           │       ├── Util
        │           │       └── Value
        │           │           └── Messaging
        │           └── tests
        │               └── ZendAmf
        │                   ├── Adobe

You did awesome work!

Arul- commented 10 years ago

If you prefer a simple structure, I would recommend

Minimalistic

|-- src
|-- lib
|-- public
|-- scratch
`-- vendor

Where

Note:- you can use restler/framework instead of luracast/restler

additionally you can have

MVC Style

We have recently created laravel/database which can be used to add database support for restler. We are planning to work on restler/eloquent for a well integrated solution.

Our recent application used it and has the following structure, where the api classes are placed in app/controllers. Remaining folders should be self explanatory!

|-- app
|   |-- commands
|   |-- config
|   |-- controllers
|   |-- database
|   |   |-- migrations
|   |   `-- seeds
|   |-- models
|   |-- start
|   |-- storage
|   |   |-- cache
|   |   |-- logs
|   |   |-- sessions
|   |   `-- views
|   |-- tests
|   `-- views
|       |-- layouts
|       |-- mails
|       `-- partials
|-- bootstrap
|-- lib
|-- public
|   |-- css
|   |-- downloads
|   |-- fonts
|   |-- images
|   |-- js
|   `-- packages
|-- scratch
`-- vendor
letsbyteit commented 10 years ago

Thanks to @Arul-, that helps me a lot! I'm going to have an API only, so there is no need for MVC. So now, it's time for restructuring my code! :+1:

roynasser commented 10 years ago

I have a directory for Restler, where I maintain the Luracast package with all of its included dependencies, for easy drop-in (except for the fixes/adaptations) upgrading, and then I have a separate folder for our own developed/maintained resources. I actually have 2 folders apart from the R3 base folder... 1 which holds API methods and other Libraries/SDKs, and one which includes other auxiliary applications, cron scripts, etc which are not Web-apis, but which can use the API methods. For this I have a custom autoloader file which basically includes my API vendor folder, and the R3 vendor folder to the include path, and then includes the R3 autoloader.

I use a "mainframe" class which instantiates classes/objects and re-uses them throughout the calls. This allows us to re-use DB connections on the same web call, etc...

Our web code and web frontend is completely separate, and we like it that way... I cringe on seeing that R3 is becoming less and less API specific and is trying to serve frontends now... :(

Arul- commented 10 years ago

Unlike other frameworks which are tailored for web application development and do api as an add on

Restler is always API first, It's architecture does not add extra baggage when not needed.

We added HTML features when we wanted to fully support OAuth2 but then realised it can be used for lot more!

@RVN-BR if you are using Restler for just API, that's fine none of the web app stuff is loaded, they only take up some hard disk space on your server.

Features like Nav (Navigation) now looks like used only for creating menu, but they will also be used for automatically adding links to the API so that we can get the full glory of REST with HATEOAS :)

We haven't documented many of the new components and their potential yet, I'm sure @RVN-BR will appreciate the features when we do!

roynasser commented 10 years ago

Sounds good Arul! As long as there is no extra baggage for modules not needed, that puts my mind at ease :)

One question I've always had... When we have a lot of API files (many api classes added), will this make all calls slower? i.e. does restler include all the files at every API call, or will it match the route and only include the required files to serve the requested API method?

thanks!

Arul- commented 10 years ago

When Restler is running in debug mode, all API classes will be initialised.

Once you turn on production mode and routes are cached, only the called api class is initialised.