Apart from discussing the pros and cons of Laravel and Symfony, I'm also going to describe instances when my personal preferences have no say, since "the weaker" framework works better for them. To make my decision during the comparison of those frameworks, I'm going to highlight those parts of each of them that show the biggest differences and then evaluate everything in favour of Laravel or Symfony. All right, let's talk about the backend development!
Programming language
You might think that, since both frameworks use PHP, there is no significant difference between them.Well, let me correct you ;)
Symfony is using what I call “a common PHP”. By that, I mean that it's written using only the universal code, so you could just modify the syntax to any other language (e.g., Java or C#) and it will still work. Every programming language has some constructs that make it unique and better than the others. Not using those constructs is a big mistake. PHP, for example, has magic methods and traits. Laravel, on the other hand, uses traits and magic methods on a regular basis. Thanks to that the code is not only much shorter and without many repetitions, but it's also easier to understand and change the behaviour of applications.
That's why the first point goes to Laravel.
The core
Another thing that Laravel and Symfony have in common is the core. Both frameworks are built on top of the set of Libraries called “The Symfony Components”. But again, this similarity doesn't mean that they are identical. Laravel added its own components on top of what Symfony provides, patching issues and adding functionality that might be missing.
Even though Laravel adds some patches, in this round I would call it a draw.
Database access
Another big difference is how those frameworks access the database. Symfony is using Doctrine, while Laravel is using Eloquent.
Migrations
In Doctrine migrations are made automatically for you, all you need to do is define the model. In Eloquent, you have to make them manually, but don’t need to define fields in the model.
I guess that would make it a draw between our frameworks.
Accessing the data
In Doctrine every time you want to access the data, you need to create a so-called repository function. Since there is no easy way to access complicated structures, your repositories might grow rather big.
In Laravel accessing the data is more fluid, but you might need some knowledge about SQL since most functions are based on SQL equivalents.
One of the biggest advantages of Laravel is its coverage of possibilities. There are many situations in Doctrine when a function that might seem sensible will end up with an error. Eloquent on the other hand was designed to accept everything. Even the most meaningless request will be parsed and turned into the valid and predictable SQL. This way you are able to make very complicated queries without risking that they won't work. With that, the point goes to Laravel.
Service Container
One of the best ideas when it comes to Symfony, which simultaneously is one of its worst implementations, is the service container. It's a way to access one service from another one by using so-called injections. For example, if your code requires you to send an email, you can specify (via one of config files) that your class constructor takes swift mailer service as one of its parameters.
Seems like a nice idea, so what is wrong? The first issue is that only services can be configured to be injected. That means you have to define everything that is supposed to use any external services as a service itself. This not only breaks the definition of services as “functions or sets of software functions that can be reused by different clients for different purposes”, but also makes a huge mess in config files.
Another issue is that not everything can be registered as a service, hence you can't access other services from every place. While working with Symfony, I often found a problem while making “toString” functions in my entities, since it sometimes required access to the translator. The only way of solving this problem was hacking the kernel to get access to the service container. This solution not only made the code look bad, but also could've bitten me during the further work.
Laravel, on the other hand, solved this issue in a different way. Instead of making some artificial config file and registering everything as services, it took advantage of Object Oriented Programming and PHP Type Hinting. If you want to access any service, all you have to do is put interface of that service as one of the parameters of functions that are called. When the function is called using the App::call() method, Laravel will automatically give you correct Services as parameters of that function.
Another way of accessing services in Laravel is via using the App::make() or resolve() functions, one being the alias of the other. Thanks to the ability to access services from the global variable, you can use any service you need in any place you need. With that - point goes to Laravel!
Template engine
The template engine is another place where Symfony and Laravel differ. Symfony is using Twig, while Laravel is using Blade.
Twig has some significant advantages, mainly a bigger community, nicer looking code, and a variety of keywords added by different extensions. So why, despite all of that, I still consider Blade to be better than Twig?
The first advantage of Blade is its reusability of code. If you make some function that you will be using in both template and controller, in Twig you'll need to define it twice. The reason of that is that in templates you cannot use PHP functions, while in PHP it's impossible to use template functions without channelling your inner hacker.
In Blade, on the other hand, you are directly using PHP functions, which means that whatever you define to be used in the controller, you can also use in the template. You can even load services directly in the template by using the @inject directive. The second advantage of Blade is how well it works with frontend frameworks or libraries. For example, if you would like to use Angular there would be a problem with curly braces which somehow need to be escaped. The solution in Twig looks like this:
{{ '{{myModelName}}' }}
on the other hand, Blade has 3 different ways of solving this problem:
@{{myModelName}}
@verbatim
You can put any code here eg. {{myModelName}}, {{myModelName2}}
<script>
//Even some javascript
</script>
@endverbatim
// Call this before using templates
Blade::setContentTags('<%', '%>');
//This is in template
{{ variableFromAngular }}
<% variableFromBlade %>
I can say that these two advantages are enough to balance the ugly looking code and smaller community - I guess it has to be a draw.
Middleware
Both Laravel and Symfony support middleware, but each in a different way.
Laravel is using decorator pattern. You create a function that's supposed to call the next level of middleware. Before and after the call it can do everything you want it to do. Symfony, on the other hand, is based on observer pattern (you are adding listeners to pre- and post- events). Each of those solutions has its pros and cons. In Laravel you have better control over what is happening with your request. In Symfony, however, you can create middleware from any point of your application. With that in mind, I would call it a draw.
Forms and validators
Form validation is a big difference between Symfony and Laravel. In Laravel validation can be done either in form or via the manual validation of a request, while in Symfony you can only validate a model.
Because of that, it's very hard in Symfony to validate the same object in multiple ways (e.g., based on permissions). In Laravel you might need to add the same validation logic to every form in which an object is being either created or modified.
Another thing is customised validation. If you would like to use either a validation rule that doesn't exist in the framework or a more advanced/multifield validation (such as “StartDate < EndDate”), in Laravel you can use the so called After Validation Hook. In Symfony you need to create an entire new Validator (2 extra files).
There's also one more issue - naming. In Symfony, validation rules were called Assertions. From the definition, Assertion is “a statement that a predicate is expected to always be true at that point in the code. Evaluating assertion to false at run time leads to an assertion failure which typically causes the program to crash." This means that Asserts are typically a way of testing programs for bugs in the code, not for the improper user input - we don’t want anything to crash if user input is incorrect. This misleading name is also something I consider a downside of Symfony.
Based on the shorter code, more possible use cases, and the ease of implementation, the winner of this round is Laravel.
Cache and performance
Caching data is currently considered a must. But what if it's not? Both Symfony and Laravel are caching their views, but only Symfony is caching source code by default. What is interesting is the fact that Laravel works faster even when Symfony is using the cache. Because of that performance boost, I've never had the need to use cache in Laravel. Both Laravel And Symfony have support for APC, Memcached, Redis, and file based cache.
This is a good place for a small sidenote. Since I don’t have a website that was rewritten on both frameworks, while benchmarking “Hello World” makes no sense and might lead to weird solutions, I picked similar-sized websites I developed with the use of each framework and compared their loading times. For Laravel the average was about 60ms, and after I've cleared the cache it went up to 75ms. For Symfony, the average was about 250ms, and after clearing the cache it went up to 2s.
This shows that Laravel is far superior regarding the performance. Since Laravel is faster and doesn't require as much cache as Symfony, I think it also wins this round.
Debug and Development tools
Debugging is a must for every application. A good IDE support, as well as debugging and profiling tools, will help you find issues in your code much faster. When it comes to IDE, Symfony has much better support. The support for Laravel is very minimalistic, but it has a library called laravel-ide-helper that fills most of the holes.
Now let's take a look at the debugging tools. Symfony has a very advanced panel showing most of the issues, as well as profiling details. Laravel has only a simple panel capable of displaying exceptions and doing some basic profiling. With that, in this round a definite winner is Symfony.
Third party software
So far it looks like Laravel is far superior to Symfony. Well, there is one instance when Symfony is the definite winner - I'm talking about working with the third party software. There are few big teams that spend their time by making additional packages for Symfony. The main thing about those teams is that their work is featured in Symfony’s official documentation and their packages are commonly used. Probably every Symfony developer knows what Sonata or liipImagine are. Less specialised teams include FOS and KnpLabs.
Those third party packages can make Symfony development much faster at some points, but there is one issue you should consider. If you are aware of the KISS principle and reason why it's better to make smaller things, then you already know what I am going to say.
All of those third party libraries are huge and give Developers a variety of possibilities. However, they also have a lot of bugs. As a Symfony Developer, I found myself spending more than 50% of my time on fixing/working around bugs and issues in those libraries rather than on focusing on my own code. The low code quality of those libraries, as well as the lack of proper refactorization, make them quite hard to work with. So if you know that you are going to need something more than a basic functionality provided by those libraries, you'll better check if you won't get stuck with fixing something you were not planning to even worry about.
When it comes to Laravel’s third party community, it undeniably is quite vast, but I found that many packages are made by small teams or even a single Developer. That means that a package that was in the top 10 yesterday, tomorrow can be dead. There are many libraries that are doing the same things, so you have a big pool to pick from. However, you can't count on either any standardisation nor the fact that those packages will work together well. Your best bet in most cases is to write your own code.
One more difference between Laravel and Symfony is how Developers acquire packages. Laravel has its own package database. Symfony has no such tool, so you'll have to use Google. But, as I've said, many popular packages are mentioned in the documentation. This is why I think that Symfony won in this round.
Admin panel
Admin panel is a must for the current websites. Symfony contains exactly one, standardised, and very advanced admin panel - Sonata. On the other hand, Laravel has a few packages that can be used as an admin panel. So far I have only tested two of them and concluded that it's better to write your own panel than use one of them. Maybe there is a good panel for Laravel, but I have not found one.With that in mind, this round's winner is Symfony.
Modules
There are quite a few commonly used libraries and modules outside of the framework. Some of them are supported better, while others are a bit worse. In this part of my article I will cover few of the most popular externals.
Search engine
Usage of elasticsearch or Solr became almost a must on modern websites. Both Symfony and Laravel support them by using third party packages: FOSElastica and KnpBundles for Symfony, laravel-elasticsearch and laravel-solarium for Laravel. No point having a discussion - it's a draw.
External Drive
Some websites may need to use more space than a host can provide. The typical solution in such a case is using either Amazon S3 or some other cloud system. Symfony handles those external drives by using third party package that is based on gaufrette (13 adapters), while Laravel handles them by using internal libraries based on flysystem (20 adapters). What is interesting, one of flysystem adapters handles gaufrette as well. With that the point goes to Laravel.
Sentry
Debugging is hard if we don’t know what caused an issue (or when it happened) - that's why sentry is so popular. Symfony gets access to sentry by using sentry-symfony, while Laravel is using laravel-raven. We have a draw here.
Laravel vs Symfony - which is better?
The final score is 12:9 in favour of Laravel. But does this mean that Laravel is the ultimate winner? I for sure don't think so.
Even though in most use cases I would pick Laravel as the best framework, there also described a few instances when Symfony is simply better. With that in mind, you should always pick the framework based on the project requirements rather than the superiority of one framework over another. But if you are still not sure which framework to pick, just go with Laravel :)
Navigate the changing IT landscape
Some highlighted content that we want to draw attention to to link to our other resources. It usually contains a link .