As I mentioned in my first post, when I started using Laravel I knew nothing about the concept of MVC. It was difficult to transition from writing pure PHP (which I had only learned 6 months prior to working with Laravel) to an MVC framework. There a lot of great resources for MVC noobs —tut+’s MVC for Noobs is one—and introductions to Laravel—Laracast’s free Laravel From Scratch series is one, Laravel Book’s Architecture of Laravel Applications (http://laravelbook.com/laravel-architecture/) is another—but let’s quickly recap the basic concepts.
The MVC Pattern
At its core, the MVC architectural pattern exists to help with the Separation of Concerns (https://en.wikipedia.org/wiki/Separation_of_concerns) in your code. The MVC pattern consists of:
- Models: represent stored data and enforce “business” rules/logic on the data (in Laravel, a model is analogous to a table in your database)
- Views: present data to the user
- Controllers: mediate between the View and the Model
In Laravel 4, the app directory has folders for controllers, models, and views. You would expect the typical flow of information would go like this:
- A route is invoked
- The route calls a function within a controller
- The controller uses a model to access data
- The controller passes that data to a view
- The view displays the data to the user
And in it’s most simplest form, that’s exactly how the Laravel framework works. Looking at the files that are included in a new Laravel install (at least in Laravel 4.x, this is changing with Laravel 5.x), this made sense. And so I moved forward believing that everything must fall into a model, a view, or a controller.
My Controllers Needs A Diet
The first feature I created for the SimpliFit beta API was simple: show all the habits a user has learned since they started with SimpliFit. We called this feature Achievements. “Easy enough,” I thought as I created a few models, coded the relationships, and seeded the database. In the end, my one controller function had ballooned to over 100 lines of code while my models were at about 30. I tested the feature and it worked.
Then I heard the saying “skinny controller, fat model”. Reality check time: my controller was pretty fat. Since I was coding an API, we didn’t have any views in Laravel for this feature. That just left the model, and so I thought all the business logic I need must go into the model.
As I coded more features, I ensured that my controllers only passed data between the user on the front end and the database, and I moved all the logic into the models. Even with this, I still have controllers that are 400+ lines of code (and only two functions), but my models are beastly—I have several models that are over 2,000 lines of code!
This is obviously a maintainability nightmare. With 49 models and 20 controllers in total and thousands of lines of code, I knew there had to be a better way of organizing my code. The standard MVC principles weren’t cutting it for me.
Repositories, Interfaces, and Commands, oh my!
When I was in the midst of coding SimpliFit beta v1 in June and July, I thought I had a good grasp on Laravel. I was able to code features and they worked as intended. At the time, I wasn’t concerned with coding to best practices, I just needed something that worked.
This is about the same time I subscribed to Laracasts.com (well worth the $9 per month) and started learning there was so much more to Laravel than models, views, and controllers. I’m still trying to wrap my mind around all the concepts, but now I know that I can employ various types of coding patterns and ideas (beyond models, views, and controllers):
- service providers,
- entities, and
- more I probably haven’t learned about yet.
A word of caution
A lot of beginner Laravel sources tend to oversimplify MVC concepts. Some sources even have you put code into your routes.php file, which, although won’t break anything in Laravel, it does go counter to the Separation of Concerns principle. When I first started, I thought I had to stick to models, views, or controllers. I didn’t know that there were more options.
If you’re an MVC noob like I was when I started with Laravel, if you take anything away from this article, let it be this: don’t constrain your code to just models, views, and controllers—learn about the other options that exist for organizing your code. Even if you don’t adopt those practices at first, you need to know about them so you can make more educated decisions about your app structure.
If I could back to when I first started with Laravel, would I force myself to adopt these other coding patterns and ideas? Maybe. For us, getting our app out to users for testing was our first priority, and the faster we could achieve that, the better. But if I had known about my options, I may have at least coded in a way that would have allowed me to adopt these patterns down the road more easily.