An Expanded Laravel Project Structure: Overview
The default Laravel project structure has always troubled me somewhat. Some of it could perhaps be attributed simply
to a lack of familiarity, having come to Laravel from the Symfony ecosystem, but whatever it is, I can't seem to get beyond
a fundamental discomfort with the fact that the bulk of the project is buried beneath the
/app directory -
application layer, domain model, infrastructure, some (but not all) configuration, logs... nearly everything. In fact,
only vendor libraries and the public directory (along with the remaining configuration) are exposed at the topmost level.
Recently it has become the practice of many to replace the
/app/models directory with a namespaced model
directory. While this clearly isolates the domain model from the rest of the project, it doesn't solve the real issue:
though isolated, the domain model remains within the
/app directory together with so many other
As a result, I've been experimenting a bit recently with a new Laravel project structure, one which I think does a better job at keeping logically discrete components of a project separate; an example of that structure is to the left.
As it stands, a number of workarounds are required to arrive at this structure due to several hard coded paths in Laravel's core.¹ Fortunately, none of the workarounds are so cumbersome that they can't be easily automated with Foreman or similar. I plan to cover these workarounds in (a) future post(s).
The first thing that you'll likely notice (aside from a level of influence from the Symfony 3.0 folder structure, recently removed from the 2.5 branch for the time being) is that the structure is expanded considerably, that there are far more top level directories.
Let's examine those directories one by one...
/appdirectory remains, but it is now home to only the http and application layers of the project(s). In the example above, three related applications share the project space; Admin, API & Client. While I would typically extract each of these into their own project, during development I will often have them living together as they all rely upon a single domain model (in production the domain model, living in its own repository, would be vendored into the various projects which consume it via composer; for a project having only a single application this, of course, wouldn't be necessary). Within these application directories you'll find what you might expect to see in the http and application layers; controllers, routing, presenters, composers, transformers, views, etc. I'll typically namespace this directory (or the individual application directories it contains in the case of a project with multiple applications). Aside from the question of separation of concerns, I find having the http and applications layers isolated within a single directory to be very convenient for front end developers.
/bindirectory simply surfaces the executables normally hidden beneath the
/vendor/bindirectory as a convenience.
/etcdirectory is a catch-all for those project components which support the application, but which are not part of the application. Several of the subdirectories are my own, but two, the
/databasedirectory I've relocated here from their home elsewhere in the default Laravel directory structure.
/srcdirectory is the home of the domain layer and it's supporting infrastructure. I typically namespace the subdirectories separately. This is where a 'backendian' like me is going to be spending most of their time.
/sysdirectory is home to bootstrap and configuration. For now, a modified routes file lives here as well due to limitations in Laravel's core. The upcoming default Laravel project structure addresses this issue, moving routing to service providers.
/vardirectory is essentially the
/storagesubdirectory of the Laravel default structure. Since the content of this directory is the output of the project rather than part of the project itself, it lives in a directory outside of the project. The directory name follows the standard *nix convention for directories containing system output.
/vendordirectory is created by composer. So far, I have resisted the urge to alias it as
/wwwdirectory is the Laravel default structure's
/webdirectory aliased to be more in line with the common *nix naming convention for publicly available files.
¹ A proposal was made to make the project structure more configurable, but at the time Taylor felt that convention served most developers well. I revisited the issue in part in a subsequent proposal which was somewhat more well received. Yesterday, I was happy to learn (by listening to the most recent Laravel.io podcast) that Taylor has incorporated a new default project structure in his plans for the upcoming 4.3 release. I'm really hoping that along with the new default structure we gain more options for configuration. While I'd concede that the majority of Laravel developers would likely be content with a simple convention, the diverse Laravel community unquestionably also includes many for whom directory structure is an important project consideration.
- Laravel 4.2.*