After creating an API with Laravel 5 about a month ago, I was really liking the new directory structure and some of the features that were available. Today, I tried to replicate this magic and was having issues getting a stable version of Laravel 5 (which is to be expected to a degree since Taylor is still deciding some of the bootstrapping process). Then it hit me.

I can make Laravel 4 act a lot like Laravel 5!

Most of what I liked was the structure and use of service providers to boot things. With the development process that we've created with our team, some of the new features like Annotations, Elixer, and Request Validations aren't on our list to adopt adopt. So, after a bit of scratching my head, I was able to come up with a way to set up Laravel 4 to work similar to Laravel 5 (and hopefully make converting to Laravel 5 REALLY easy).

src Folder

The first thing that I do is create a src folder for my application code. Then I put in some basic folders (somewhat inpired by the namespaces included in the bootstrap project for Laravel 5).

src/
|-Http/
| |-Controllers
| |-Requests
| |-Responders
|-Models/
|-Providers/

Strip out app

From the app directory, I delete the folders for controllers, commands, models, and tests. And, I delete the routes.php and filters.php files. Then, I move the database, and storage folders up to the root level of my project.

Then there's some updating to do in the app/start/global file. I go and remove commands, controllers, and models from the class loader, and I update the app_path().'/database/seeds' to base_path('/database/seeds').

I then need to remove and update the autoloader in my composer.json file to look like this:

"classmap": [
    "database/migrations",
    "database/seeds"
],

resources

Next, I move the app/views directory to resources/templates (I prefer to call these templates since I refer to the objects that perform the actual rendering views). To make this work in the framework, I then go to app/config/view and update the paths to array(base_path('resources/templates')).

Autoloading with PSR-4

Now, I go and update the composer.json file to autoload the src/ directory to my application/vendor namespace.

Bootstrap Provider

In order to make my src directory as easy as possible to drop into any project, I create a single service provider called BootstrapServiceProvider in my src/Providers folder. It then looks like the following:

class BootstrapServiceProvider extends ServiceProvider
{
    protected $providers = [
    ];

    public function register()
    {
        foreach ($this->providers as $provider) {
            $this->app->register($provider);
        }
    }
}

Now in app/config/app.php I just need to refer to this single provider. And when I'm building my application itself, any new service provider that I want to load within my own application namespace just get's thrown into the providers array in my BootstrapServiceProvider.

Routes Provider

I then can create a routes provider that looks a bit like this:

class RoutesServiceProvider extends ServiceProvider
{

    protected $namespace = 'Acme\\Http\\Controllers';

    public function register()
    {

    }

    public function boot()
    {
        $router = $this->app['router'];

        $router->group(['namespace' => $this->namespace], function($router) {
            require __DIR__.'/../Http/routes.php';
        });
    }
}

And now in my src/Http/routes.php file, I can use the $router variable to declare routes rather than using the Route facade.

Build from there

Right now, that's about the needs for my application to make it structured like Laravel 5 and pull out some of the weight that was in the original app directory. As I need them, I create more service providers to alias interfaces, register events, register class based filters, and more.