The great PHP MVC Framework Showdown of 2016 — (CakePHP 3 vs Symfony 2 vs Laravel 5 vs Zend 2)
The state of PHP MVC Frameworks, 2017 Update
— Hey buddy, it’s 2015!!
— Dohhh…
I do hope that some of the things I’ve come to see and understand over the years regarding various PHP MVC frameworks will remain true for at least another half a year. I’ve mustered the strength to write this up only after I had at least a few years of professional experience with each of the contenders… and about ten years working with MVC in general.
To be honest this type of post is only useful for a short while. Web development world is too fast paced to definitively say which framework or tool is going to rule the world. Just when something new comes out, another project seems to spring out of nowhere to steal the show.
However as we dig deeper into the features of each framework, certain patterns begin to emerge. We discover coding styles, configuration and setup requirements, modularity, performance, usability, learning curve and overall architecture. Invariably these lead to some sort of character development, a flavor, a unique approach to solve the problem of properly implementing the MVC paradigm. And as we already know MVC is a concept, which is somewhat open to interpretation.
Popularity contest
Glancing at the data from google we can see some clear trends. (Not to be confused with “winners”; not for this comparison).
- Laravel is the new kid on the block, soaring in popularity.
- CakePHP is falling behind, largely because Cake3 came kinda late to the game.
- Symfony(2) is consistently stable.
- Zend is slowly dying… or not… it’s been a downhill battle for Zend either way.
Why didn’t I include CodeIgniter? While I’ve heard great things about CI3, it’s still in the very early stages and, IMO suffers from the same fate as CakePHP 3. While CodeIgniter is no doubt a popular framework its serious lack of a decent ORM has plagued my opinion of it for years… and to this day I believe that M (aka the Model layer) is the most important part of an MVC framework. Call me crazy, but due to this fact alone I cannot consider CodeIgniter as a strong MVC player. (Each framework has its time and place, but here I’d like to highlight the top contenders, which are ready for enterprise-level systems). Also, I don’t have enough experience with CI… so wouldn’t be very fair to be discussing something that I only know in passing.
That said, while these trends can tell us the general state of things, it is certainly not enough information to make a decision about which framework to use.
We need to really take a look at each one in just a little more detail…
#1 Symfony
In some ways it’s an easy choice. While it may not be the most trendy framework, it is certainly the most stable. Over the years it has captured a tremendous amount of momentum and what made it even greater is the impact Symfony community had on PHP in general, tools like composer, Doctrine or PSR standards are in no small part had become the de-facto standard for many other PHP toolsets because of the Symfony’s efforts (to be fair, not just Symfony alone).
Symfony components not only establish the base for the Symfony2 MVC framework, but the Laravel framework was born out of these very components as well. This definitely goes to show that as far as striving in the PHP ecosystem Symfony seems to be on top of their game.
Their mission statement alone makes me smile:
Symfony is a set of PHP Components, a Web Application framework, a Philosophy, and a Community — all working together in harmony.
Symfony is extremely modular. Everything in Symfony is a bundle (of MVC goodies), which makes the framework architecture very extensible and flexible by design. It works wonderfully well with composer, namespaces and autoloaders… all important aspects of a well structured application.
I would argue that because of the ability to use various ORM systems (i.e. Doctrine or Propel) Symfony is a beloved framework. If we are honest and true to the MVC paradigm, and keep our business logic in the Model layer, having this flexibility of ORM style is a fantastic opportunity for any developer to pick and chose their preferred programming philosophy. That’s powerful.
One should not ignore the community around each framework. Symfony has a very knowledgeable community with many questions having a variety of clever and interesting answers.
That said Symfony is somewhat complex in its structure, it is “bulky” and requires a fair bit of configuration, which can be confusing to grasp at first. However, I also feel that Symfony strikes a great balance of being highly modular and configurable, while maintaining a level of comfort by overall employing rather simple configuration strategies (i.e. YAML files or annotations). Once the developer understands the overall structure of the application things begin to fall into place rather quickly.
#2 CakePHP 3
I love cake’s mantra: “convention over configuration”. While some disagree and say that CakePHP has entirely too much auto-magic, its power lies in nearly effortless configuration. Just follow some basic rules and you can start developing powerful applications in no-time. (Or just turn on “scaffolding” and magically views and forms are created for you, or “bake” the entire app… all based on your DB schema and relevant definitions).
One could say that I am biased towards CakePHP, since I’ve been working with it for so long, and while that’s true I’ve also spent about 4 years with Symfony, Magento and Zend… I have also worked with Laravel 4 & 5 for a little over two years, so I truly hope that gives me enough developer insight and a solid understanding of the underlying concepts of each framework.
And that’s what really distinguishes one MVC framework from another, the philosophy behind it and the code architecture. How did the core team solve the paradigm of MVC? Is the framework truly extensible and scalable? Does it fulfill the meaning of rapid application development philosophy?
This is where CakePHP 3 shines, the developers took the time and effort to learn as much as they can from other frameworks (even such as rails to some extent) and previous CakePHP versions, apply some great principals such as aforementioned “convention over configuration” and ORM that was built from the ground up.
And I have to say of all the PHP frameworks cake’s ORM is probably the most pleasant to work with. There is a bit of a learning curve to grasp the concepts, but once you do… the way it elegantly handles associations between tables as well as data-saving and validation, is just a joy.
Perhaps it simply jives with the way my brain works, but things in CakePHP just make sense.
For applications that require RDBMS functionality CakePHP kicks ass!
Cake’s problem? CakePHP 3 arrived just a little too late and it just isn’t mature enough. There are some great applications already built on CakePHP 2.x, and migrating everything over to CakePHP 3 (there really isn’t any backwards compatibility) leaves people wondering if they should opt-out for Laravel instead, yes I’ve been in that boat myself. I do have a personal dislike for the core lack of support of MongoDB. It is rather simple, while CakePHP 3 supports ElasticSearch (sometimes considered superior to mongo), it’s kind of like including support for PostgreSQL and bypassing MySQL. Modern frameworks should offer support for majority of popular data stores and MongoDB is definitely extremely popular. The beauty of it is that there should be enough community support to make that happen.
… And CakePHP community is fantastic, it often feels like a little “click”, but that is what makes it great. I’ve been a part of that community for years, and have learned a great deal about good architecture and programming by following (or sometimes avoiding :) ) the teachings of great developers behind the framework.
I didn’t get into details of Symfony’s ORM because it uses either of the two pretty much stand-alone libraries. Cake’s ORM is different.
In the previous versions CakePHP 2.x the ORM got some hate because it wasn’t truly OOP and wasn’t very flexible. I have to say that cake developers did a great job refactoring the ORM. The model layer was revamped with Entity and Repository classes, which represent records and tables, respectively. This is a welcome addition and shift, making the ORM a lot more object oriented in nature and provides a great level of flexibility when writing and testing your code.
Additionally there is a certain level of similarity between Symfony’s and CakePHP 3 ORM. I would say that I prefer cake’s just a bit more, but it is due to a much simpler initial configuration and coding philosophy. Practically, however, it truly is a matter of personal choice.
#3 Laravel
The little baby of Symfony. Although it’s almost all grown up you do have to admit that it leverages a great deal from Symfony… and actually that’s fantastic. Not only does it not try to reinvent the wheel, Laravel also keeps things simple. It uses stable, proven and solid Symfony backbone to setup an entirely new way to code within Laravel’s own MVC world.
Perhaps some things are kept overly simple for my taste. Lack of structure is something I cringe at whenever I see fat controllers or logic sprinkled in places where it doesn’t belong (keep separation of concerns in mind)… To be honest, that’s where I lost trust in CodeIgniter.. it was too loose and “open to interpretation”. Of course, there is exactly opposite school of thought, which says “over-engineering is the root of all evil”. And I agree, but I wouldn’t agree with keeping something simple while sacrificing the quality of the code and maintainability.
Technical debt is a real and very serious thing for any IT system, which is present in any modern company be it an accounting system, a CMS, a gaming app, or a web property of some sorts. Trying to repay this debt “later on” can lead to a real bankruptcy.
Unlike CodeIgniter, Laravel does a much better job of enforcing some structure, but not quite as good as CakePHP.
It also leaves the architecture a little more open for 3rd party plugins (packages) rather than following a more strict plugin structure of CakePHP. I would say that such approach has both pluses and minuses. While in most cases it’s much easier to re-use an existing component. Completely relying on third-party libraries can eventually lead to a maintenance nightmare, something that larger Symfony projects often suffer from as well.
Eloquent ORM is Laravel’s greatest strength, as it is its weakness. It reminds me of an earlier version of CakePHP’s ORM. Yeah it’s great and simple, but because it’s so simple it is not as well structured and granular as CakePHP 3 (or something as advanced as Doctrine). However, one would say that this is exactly the way it was intended to be, and I can’t really disagree with that.
Yet, one conclusion I would draw from that is that Laravel is probably best to use as a front-end framework, which does not require complex data store functionality. It is perfectly suited to be a service layer with its integration to Iron.io and other popular SaaS providers (AWS, S3, sendgrid, etc.), Laravel provides a simple way to build and consume API’s and a clever and (again) simple way to setup routing. As said, it’s a perfect interface to a more complex back-end system if there is such a need.
Unit and functional testing is something that I should have mentioned at the very beginning, but at least I’ll devote a paragraph to it here. Unit testing in Laravel is a pleasure. (Actually all aforementioned MVC frameworks have fantastic testing facilities).
Laravel, following its KISS model, makes no strict guidelines as to how to structure your tests, but it does provide all the necessary tools to write effective functional and unit tests to give you exactly what you are after — good level of code coverage.
#0 Zend
Not unlike Symfony, Zend also provides a collection of components, however… very much unlike Symfony, Zend does an extremely poor job of helping the developer to leverage them. Yes, there is solid documentation and tutorials, but Zend framework is missing the most essential part — The framework.
The collection of components by themselves is great, but every time you write an application or even a part thereof, you have to pretty much write a mini-framework just to get things to tie together.
As far as development philosophy of extremely heavy configuration (yes, the amount of config and coding required to start writing a controller is enough to write a little application in most other frameworks), I simply cannot embrace that.
Additionally Zend does not provide any ORM or a decent API to facilitate an integration of one (like Symfony), which leaves the Model layer entirely too loose. This, as I’ve mentioned above, can often lead to poorly structured and untestable code, fat controllers, and other OOP violations.
Although both Zend and CodeIgniter support Doctrine ORM integration, neither provides a native interface to use it. While the integration may not be overly complex, it again requires more and more overhead and configuration (and coding).
For Zend, it would best to drop the framework effort and dedicate their resources by teaming up with Symfony and really influencing the PHP community in a positive way. All in all we wouldn’t have questions like this. And I don’t think we should. Their components could be very beneficial to the community especially if paired and refactored into Symfony’s ecosystem. Zend’s effort at the “framework” seems to be an uphill battle, while all the necessary aspects of integration are already implemented in Symfony. It just doesn’t make a lot of sense to spend all this time building something that desperately needs the missing link, which is already available in Symfony MVC.
Here’s the thing, if this is what it takes to write a single basic “blog” module that pretty much has no logic, then the framework does not satisfy the requirements of RAD (rapid application development). It makes things hard to configure, maintain and troubleshoot. By contrast in CakePHP all you’d really need is a table called “blogs” with aforementioned fields… talk about automagic.
Controllers, Routing
I would say that all of the above frameworks offer a pretty solid routing system and controller setup. I don’t want to dwell too much on this part, since I really have no complaints or preferences about how each framework chose to handle these parts of the system. Also while routing is important, the controller layer just like the controllers themselves should be light in implementation and mostly delegate requests to other parts of the framework.
I should mention that CakePHP’s routing is pretty clever, with all sorts of interesting options. As you’d expect Symfony’s is very configurable (and in some ways that can be pretty annoying, having to map everything, albeit in YAML files or annotations, which I am not crazy about)… and Zend, as it stands, will require you to write a ton of code to achieve something rather simple.
With CakePHP you get most routing features right out of the box, i.e. you don’t have to setup anything, just name your controllers and views according to the rules and everything will be routed for you.
This is where CakePHP’s routing is powerful, but often misunderstood, because some developers may never have to get to the more complex routing setup. Once you do, then you really have to dig deep to understand all the hidden gems.
Just another area where each framework solves the problem in its own right, but each one does so in a pretty sound technical way following their own coding methodologies.
Templating and Views
While PHP itself was created as a templating language, there are a few reasons why you might want to chose another templating engine to render your views. One obvious reason is that many designers do not like working with embedded PHP code, and while there is nothing scary about it, if you have a front-end team that prefers to work with a specific templating language, then it has to be considered. Thus having a flexibly of choice is kind of important.
CakePHP and Zend use plain PHP views out-of-the-box, while Symfony and Laravel use Twig and Blade respectively. I don’t see anything particularly useful about blade, other than a cleaner syntax than PHP, while Twig offers template rendering/caching and some level of template-layer security.
That said, you can switch your templating engine in each of the frameworks, so if you aren’t happy with the defaults and chose to use Twig, for example, then you have an option of doing so.
If I had to go with a choice of a templating engine that is available out of the box, I’d recommend Twig.
In Twig, your template designer can’t easily take shortcuts. Eg. calling a query in your templates. They’ll have to pass the result to the view or allow access to a certain function (or ask the backend developer). The downside is that it is more work to just call a simple function/filter sometimes.
This alone makes me want to chose Twig over any other templating engine. I’ve seen plenty of apps that do crazy things like attempt to access DB information from a completely unacceptable place (i.e. the View or partial or element, etc.) and then do relatively heavy data manipulation right in the template. This kind of short-cut breaks MVC and violates separation of concerns, therefore from the maintenance perspective and even TDD it should be avoided at all costs.
Nice writeup on Blade vs Twig comparison.
Documentation
All frameworks have pretty solid documentation at this point. While each one was faulted for lack thereof in the previous years, I firmly believe that documentation for an open-source project is a community effort. No framework should be blamed for lack of docs, however the creators of the framework are responsible for putting forth some foundation for quality documentation of the framework’s features.
With all that said, here’s my quick take on the situation.
Personally I prefer the documentation with open comments as Zend has it, there are often more great answers in the comments than in the doc itself. Given the complexity of Zend the documentation seems to be a little light on the details of some implementations.
Laravel’s is a little skim, because the framework is kind of new, but it does a good job of covering the things you need to get going.
Symfony only covers the basics and I wish it would elaborate on some topics.
CakePHP’s has matured to be quite good and extensive.
That said, you can pretty much find an answer to any common problem with each of the frameworks in minutes, by firing up your trusty search engine.
Conclusion
So who’s the winner? Which framework should you use?
That was a lot of writing with nothing clear emerging so far, although you probably gathered that I like CakePHP, dislike Zend, think that Laravel is slightly overhyped, and feel very passionately about Symfony.
However, my feelings and emotions have little to do with what’s best for your project.
Use the right tool for the right job. (I’m sure that’s what you wanted to hear).
If you need an extremely modular and well supported framework go with Symfony 2, if you want fast prototyping and ease of use go with Laravel 5, and if you want something in-between go with CakePHP 3.
Besides, you should make some decisions before making your choice.
For example: what is your data store(s), how well does the framework support it out of the box? Do you understand and agree with the framework’s coding concepts after looking at a tutorial or two?
How’s the community support? Are there enough documentation to understand how to solve basic things like data validation and traditional CRUD operations? Last, but not least, what technology do you have in place now? If you are running Microsoft SQL server and everyone on your team knows python, perhaps a PHP framework is not the best solution.
The framework has to make sense to you and/or your team of developers. First and foremost development within any framework should be making your life easier, but one should anticipate a learning curve and in many cases it can take well over a year to really understand the nuances of a given framework.
I didn’t include micro-frameworks (i.e. silex, slim) as they tend to fall into a different category. After some pondering I might just do another write up on that. After all, as we see, more and more often the general trend is to move away from complex monolithic applications to a more micro-service-oriented architecture.