Re-organising Laravel applications with PSR-4

I find the initial Laravel project structure quite approachable:

  • app/
    • commands/
    • config/
    • controllers/
    • database/
    • models/
    • storage/
    • tests/
    • views/

However, as your application grows, you'll likely find it difficult to structure without namespaces. Larger applications typically end up with a structure like so:

  • app/
    • commands/
    • config/
    • controllers/
    • database/
    • MyApp/
      • Models/
      • Repositories/
      • Services/
    • storage/
    • tests/
    • views/

A bit confusing. You might move commands and controllers into namespaces as well, only to end up with much longer route configurations and sadness.

Fortunately, with PSR-4 we can restore the situation. PSR-4's autoloader allows us to map namespaces to arbitrary paths, which unlike PSR-0 don't contain any of the namespace. For example, we can modify composer.json to namespace everything in the default Laravel classmap, while retaining the simple structure:

"require": {
    "laravel/framework": "4.1.*"
},
"autoload": {
    "psr-4": {
        "Acme\\Commands\\": "app/commands",
        "Acme\\Controllers\\": "app/controllers",
        "Acme\\Seeders\\": "app/database/seeds",
        "Acme\\Models": "app/models",
        "Acme\\Repositories\\": "app/repositories",
        "Acme\\Services\\": "app/services"
    }
}

Note that migrations can't be namespaced, as Artisan won't pick them up (hat tip /u/meddyiscool).

Now we can place our models in app/models/User.php, yet retain the namespaced structure of Acme\\Models\\User. With PSR-0's autoloader, this file would exist in app/models/Acme/Models/User.php.

While the more common benefit of this will be to eliminate superfluous directories in libraries with a vendor namespace, I'm excited to restore the simple structure of my Laravel applications.

Composer's PSR-4 autoloader is already available: run composer self-update, if you haven't recently.