Laravel 4 is your usual MVC setup. You have an application directory, which houses all your controllers, models, repositories, views and more. This works very well, and has done for a long time for various frameworks in every web development language available. However, for large applications this can mean a large codebase which can be difficult to manage, especially as the application grows. Unfortunately, not every framework provides the tools to be able to modularise your development and workflow. Laravel 4 does. When you install L4, you get two very nice features (along with all the rest):
- Composer packages and support
- The workbench
You should by now know how to use Composer - it’s required for Laravel 4. What you may not be used to or familiar with, however - is the workbench.
Much like Composer, which deals with packages from packagist.org - the workbench also deals with packages, but local ones. In short, it can be used as a test bed for releasing your own packages, or better yet - as a house for your application modules. What I mean by that is you can setup different packages for different parts of your application and have them talk to one another. In this way, you create a more modular application that is less dependent on individual pieces. I am of the firm belief that the best way to learn, is to do - so let’s get started with the concept.
An alternative arrangement
The whole idea of this article is to provide an alternative way of building your application. What we’ll do is separate the three main domains of our application into 3 separate packages:
- A package for managing data
- A package for API requests
- A package for an admin panel
Arguably, we could create a 4th package - maybe for the front-facing part of the application (such as the brochure site or something similar), but let’s keep it simple for now. But first I’d like to quickly explain why in these examples I’d split them into various packages.
For starters, models and repositories are something that I find I re-use across applications. Especially in large applications where I may have each application dealing with the data in slightly different ways, but want to share code via gitsubmodules or similar, then it makes sense to have these data-related operations in their own package.
For the API, which usually handles it’s own routes and the like, we’ll again separate this out. For two reasons:
- API requests are generally done (in this example) from the client (maybe we’re writing a one page app?), or many clients (API service)
- API requests usually follow some sort of versioning convention. Our package will help to manage that.
And lastly, our admin panel - which is normally separated from the front-facing application/website. Simply keeping it separate keeps it clean and DRY. We may not re-use this code in other applications, but packages provide a logical separation that helps us to manage our code and keep it clean. There’s nothing worse than seeing for example, a UsersController which handles users for admin management, front-end registrations/signup, profile settings and more. Better yet, we could have 3 separate UsersControllers, all namespaced to their packages that deal with those business cases. An admin users controller for managing users, a front-end users controller for managing registrations/profile updates.etc, and probably one for our api. And again, these would all be talking to the one package for data queries, saving records.etc.
But Kirk - that seems awfully repetitive. It may seem that way - but when you separate application domain logic like this, it keeps your code smaller and far easier to manage. The only thing we’d really be repeating, thanks to our data being in it’s own package - is the controller’s name. Let’s move on and start setting up our packages.
Setting up our packages
We’ll use built-in Laravel tools to do this for us. We’re going to create 3 separate packages:
These will all be namespaced under our own name, but you can call it whatever you want. For me, I did the following:
I’ve included the resources flag, to ensure that each package has a laravel-ish setup. That is, it contains the usual laravel folders: migrations, config, views, etc. (For more information on package generation, see: Laravel package development). We’ll probably remove migrations from our other packages, as that will more than likely be handled by the “data” package, but that’s neither here nor there at this point in time. So from this point, how do we manage common tasks, like calling controllers, loading models.etc? Pretty easily, let’s go through that.
Dealing with our data package
The main role for our data package is to manage data. That means: data queries, creating and updating records, removing data.etc. Our data package will manage 3 core domains of code:
Our repositories are there to manage the data requests. Models define how our data looks in the database as well as setting up relationships and behavioural rules. So in that respect, we shouldn’t be dealing with models directly from other packages. Repositories are for that. And lastly - our migrations - for setting up and managing our database schema.
The important thing to note when developing with Laravel this way, is to remember what your packages are designed for. Just like when dealing with controller, model & view folders, which all have their respective classes and files for specific roles, so do packages, it’s just a bit more broad. We’re talking about the various application domains rather than the files and classes themselves.
The API layer
Our API for our application just like every good API, should be RESTful. This package will manage the various controllers and routes for managing API requests. Additionally, it -could- manage API versioning itself, or better yet - have a separate package for each API version. This lends itself well to our modular design, and because we’ve separated our API layer from our data layer, means it’s far more flexible. Remember that API versions should be differences in dealing with the API layer itself, rather than any internal changes. For example, our API interaction could be identical even if we change the internal code structure. We should only be supporting API versions, if the interface for dealing with the API changes.
The admin package
So there we have it - a modular (packaged) way of working with Laravel. This approach may not be very suitable for small applications. Admittedly, I probably wouldn’t advise this approach if your application is very specific, or if the application is very small. However, if you’re looking at building a development platform, or software that will be used by lots of developers, or even just want to try and alternative method for developing with Laravel 4 - this is a great approach as it keeps all the code within its respective domains. Feedback/comments welcome as per usual.