Laravel 5.0 - Directory structure and namespace
(This is part of a series of posts on New Features in Laravel 5.0.)
- Laravel 5.0 - Form Requests
- Laravel 5.0 - ValidatesWhenResolved
- Laravel 5.0 - Directory structure and namespace
- Laravel 5.0 - Route Caching
- Laravel 5.0 - Cloud File Drivers
- Laravel 5.0 - Method Injection
- Laravel 5.0 - Route Annotations (removed)
- Laravel 5.0 - Event Annotations (removed)
- Laravel 5.0 - Middleware (Filter-style)
- Laravel 5.0 - Environment Detection & Environment Variables
- Laravel 5.0 - Event Scheduling
- Laravel 5.0 - Commands & Handlers
- Upgrading from Laravel 4 to Laravel 5
- Bringing Whoops Back to Laravel 5
- Laravel 5.0 - Events & Handlers
- Laravel 5.0 - Generating Missing Events
- Laravel 5.0 - Custom Error Pages
- Laravel 5.0 - Eloquent Attribute Casting
One of the big reasons Laravel 4.3 got moved to 5.0 is because the directory structure can seem like a big shift in thinking.
I love it. The directory structure has been modified to now better reflect how a majority of Laravel developers either work or recommend working, and this will reduce some of the pain of comprehending "best practices", and it makes the entire task of understanding Laravel simpler.
What does it look like? #
app Commands Console Events Handlers Commands Events Http Controllers Middleware Requests Providers Services bootstrap config database migrations seeds public package resources lang views storage cache logs meta sessions views work tests
app directory has been trimmed down--and also boosted a little. Where it used to be a more classic Rails/CodeIgniter-style directory that holds all of your application's logic and framework config and templates and persistence and everything else, it's now primarily trying to hold your application's logic (including the business "domain")--and it's loading it all as PSR-4 classes.
As a result, Laravel-specific configuration details are now in their own directory. Resources--language and views--are now in their own directory. Database-related information is now in its own directory.
Note: There is a Legacy Service Provider (see the docs here) that'll allow you to serve a 5.0+ app from a 4.2- directory structure, so upgrading older Laravel apps to 5.0 won't require changing to the new directory structure.
What's better? #
So, why is this actually an improvement?
For starters, we're separating our concerns. The app directory was previously a bit of a catchall for pretty much all code other than frontend code. Now, it contains the core logic of your app--fittingly--and some of the particular implementation details live elsewhere.
Additionally, it's been considered best practice for quite a while to have an "App" style top level namespace for your domain logic. Getting started on a new project, for many of us, was at the very least deleting the models directory, adding a namespace folder named after our app, and PSR-4 autoloading that namespace. Now that's a native part of the folder structure, and it just got a lot easier to namespace Controllers and other aspects of your more framework-related code.
Finally, a lot of the code that used to be in procedural files (filters, for example) is now moved to classes and Service Providers. This makes execution easier to predict, reduces the amount of procedural code, and encourages more userland (i.e. "in our code, not in the framework") usage of Service Providers.
It's a little too extreme to say that the code in your app directory should be framework independent; controllers, filters, commands, and service providers will extend Laravel classes, and all of your classes may inherit from or receive injections of Laravel classes. But, this change goes a long way to moving the primary logic of your applications into PSR-4 loaded classes that could theoretically exist independent of Laravel.
Where does ___ go? #
If it's a class, or could be a class, it should go somewhere in
app/. If it's an Eloquent model, it should go somewhere in
app/. If it has to do with the traffic of your request through a web server (e.g. Controllers, FormRequests), it should go in
app/Http. If it has to do with CLI (command line interface) requests, it should go in
app/Console. If you would've put it in routes.php (but it isn't a route), or in start.php in the past, it should go into a Service Provider. And if it's a filter, it should now be its own class in
Other than that, it should be pretty clear.
How does the namespace work in code? #
By default, every Laravel app has a "namespace" that represents the top-level namespace for the app's classes. Out of the box it defaults to "App", and it maps directly to the
app/ folder directly via PSR-4.
But you can easily rename the namespace with an artisan command that will also replace all instances of "App/" (in namespace declarations in Laravel classes) with your new namespace.
So if I was starting Confomo again, I'd create the new Laravel install, and then instantly run the artisan command to rename the namespace:
$ php artisan app:name Confomo
Now all of the default-included classes in the
/app directory are namespaced to Confomo; the PSR-4 autoloading statement in
composer.json is updated; and Laravel knows to look for its filters, controllers, etc. in that namespace.
The new app structure and the app namespacing in Laravel 5.0 are helping us, step by step, increase the overall quality, consistency, and flexibility of our code. I like it.
Did I miss anything? I'm @stauffermatt on Twitter.
Comments? I'm @stauffermatt on Twitter