Laravel 5.0 - Directory structure and namespace

(This is part of a series of posts on New Features in Laravel 5.0.)

  1. Laravel 5.0 - Form Requests
  2. Laravel 5.0 - ValidatesWhenResolved
  3. Laravel 5.0 - Directory structure and namespace
  4. Laravel 5.0 - Route Caching
  5. Laravel 5.0 - Cloud File Drivers
  6. Laravel 5.0 - Method Injection
  7. Laravel 5.0 - Route Annotations (removed)
  8. Laravel 5.0 - Event Annotations (removed)
  9. Laravel 5.0 - Middleware (Filter-style)
  10. Laravel 5.0 - Environment Detection & Environment Variables
  11. Laravel 5.0 - Event Scheduling
  12. Laravel 5.0 - Commands & Handlers
  13. Upgrading from Laravel 4 to Laravel 5
  14. Bringing Whoops Back to Laravel 5
  15. Laravel 5.0 - Events & Handlers
  16. Laravel 5.0 - Generating Missing Events
  17. Laravel 5.0 - Custom Error Pages
  18. 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

Basically, the 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 app/Http/Filters.

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.

onclusion-Cay #

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


Tags: laravel | laravel 5 | 5.0

Matt Stauffer headshot

Hi, I'm Matt Stauffer.

I'm partner & technical director at Tighten Co.

You can find me on Twitter at @stauffermatt


Like what you're reading?

I wrote an entire 450+ page book for O'Reilly: Laravel: Up and Running.

You can order the eBook or print book today.