When working with larger Laravel projects, one question always seems to come up: "How do I organize all of this code?" Many people have begun to suggest new ways to go about this. Quite often, people begin to create namespaces in their Controllers, views, composers, and service directories. But, to me, this begins to be a bit of a spider of directories that just scream "I'm just shoving things into MVC". Commonly, I'll see people break out namespaces for API, Admin Panels, and the public site (Marketing). So their folder structure within app looks a bit like this:

app/
|- Controllers/
|   |- Admin/
|   |- API/
|   |- Marketing/
|- Services/
|   |- Admin/
|   |- API/
|   |- Marketing/
|   |- // random shared services
|- Views/
|   |- admin/
|   |- marketing/
|   |- // some shared views
|- Models/
|- filters.php
|- routes.php

Let's say that that you find an error in your admin code. You start by pulling up a crazy long routes.php file and find a route in there that leads you into you controller directory. From the controller directory you have to then drill down to your Admin namespace and into the controller at fault. Now you need to update your view that you edited admin.dashboard.index for instance. Now you have to go back out of your Admin namespace, up out of your controllers, then down into your views, down to admin, and finally down to the index.php view file.

Things get trickier with naming things. Views and view directories are camelCase, controllers and PHP namespaces are PascalCase, routes uris are snake_case, and route names are random mixes of whatever you seem to feel that day. This is part fault of the developer that day, but some of it is burned in convention that goes back to a mix of older MVC developers from different PHP frameworks. So, when working with larger Laravel projects, I suggest a decent amount of refactoring.

For stage one, we'll just start by creating a folder named after our application for composer to use PSR-0 autoloading to fetch. We'll call it Blog and then put Admin, API, and Marketing folders in there to organize our code. Now our app directory looks like this:

app/
|- Blog/
|   |- Admin/
|   |   |- Controllers/
|   |   |- Services/
|   |   |- Views/
|   |- API/
|   |   |- Controllers/
|   |   |- Services/
|   |- Marketing/
|   |   |- Controllers/
|   |   |- Services/
|   |   |- Views/
|- Services/
|   |- // random shared services
|- Views/
|   |- // some shared views
|- Models/
|- filters.php
|- routes.php

And to get our views to load, we have to use View::addLocation for each of our namespaces. Then our controllers and services just need to have their namespaces updated in routes.php and such. But I didn't really tell the whole truth about the views directory… Each view directory would have to have the same subdirectories as before which looks like this for Admin:

app/
|- Blog/
|   |- Admin/
|   |   |- Controllers/
|   |   |- Services/
|   |   |- Views/
|   |   |   |- admin/

This is a bit ugly to me and gets quite redundant when creating files with the command line (or with ST2's Advanced New File plugin as I like to use). And we haven't done much to work with our shared views, filters, or routes. So, now I'm going to introduce Service Providers into the mix. This will allow us to make these areas of our application separate little MVC applications with a few shared components. There are a few tricks that we will use. We will put our views in namespaces similar to the way that packages register their views using View::addNamespace. This will allow our views to loose that extra layer of repetition.

We'll start with our shared components and our Blog\ServiceProviders\Application Service Provider

<?php namespace Blog\ServiceProviders;

use Illuminate\Support\ServiceProvider;

class Application extends ServiceProvider
{
    public function register()
    {

    }

    public function boot()
    {
        // This will be our shared filters like guest and admin
        require_once(__DIR__.'/../filters.php');
        View::addNamespace('Application', __DIR__.'/../views/');
    }
}

Our shared views now will be available as Application::whateverViewWeWant. And we have our application shared views. We'll also move our models over to app/Blog/Models and likewise with any shared components.

Now to look at how we structure our sub-applications. For our Blog\Applications\Admin\ServiceProviders\Admin we'll do something like this:

<?php namespace Blog\Applications\Admin\ServiceProviders;

use Illuminate\Support\ServiceProvider;

class Application extends ServiceProvider
{
    public function register()
    {

    }

    public function boot()
    {
        require_once(__DIR__.'/../routes.php');
        View::addNamespace('Admin', __DIR__.'/../views/');
    }
}

Now all of our admin views will be available as Admin::whatever. For mental stability I also like to name my routes to match our views so our dashboard index would be Admin::dashboard.index.

Now we have a nice way to keep our code in sane order by breaking things up into smaller sub-applications.

If you are familiar with Django, this pattern may seem familiar to you as I stole a lot of what I'm doing from my short time using Django.