Drupal 7 vs Symfony 2: overview after 1 year of Symfony development

We’ve decided to switch to Symfony2 development in July 2012, if I’m not mistaken - after 7 years of (mostly) Drupal development.
There were reasons to do that:

1. Not-too-great experience with high load projects, powered by Drupal 7

Okay, Drupal is good enough until you get a project with big expectations in terms of response time for authenticated users. Nginx proxy, boost and memcached help a lot with anonymous page hits, but things are sometimes not good enough when we talk about authenticated user saving some nodes (1 field = 2 inserts to fields and revisions table, 40 fields - and you get super-slow node saving, at least on non-ssd hosting), using ajax stuff like dynamic forms (Drupal form ajax is not bad, it’s just not super-blazing-fast).
Things are getting even worse if you have big website with lots of views and fields, and you just clear the cache on production - your server can become close to non-responsive.
That’s what happened with us in several projects.
Okay, you can avoid using views and write your own replacement for fields which will store data in single table, and own ajax that do not pass all page ids of the page back to the server, - and it will probably be almost as fast as lower level framework code (yii, symfony, whatever) but what’s the point in using Drupal then? The code will be uglier (let’s face it, Drupal API is not as clean and decoupled as Symfony2 API). The amount of time spent on the development will probably be close.

2. Settings in DB

Drupal was built to allow anyone to create complex website without writing a line of code.
It sounds like an unrealistic dream for most of website developers, who are using raw PHP/Ruby/Python/whatever, but not for developers who are using Drupal! Latest version of Drupal and Views is indeed very close to this amazing dream.
As a side effect, when you are creating project where you need lots of programming, you are struggling with settings-in-db approach.
Of course, there are Features which allow to do an impressive deployment stuff.
But then, when you get a bug in features during deployment, which occasionally deletes fields from user profile on production (we indeed encountered this bug in production once - god bless db backups!), you think “I’d better write my own code, it’s too much magic”.
Still, I think that Features are a brilliant piece of functionality and approach.

3. One of our biggest customers fall in love with Symfony2

These guys asked if we’ll be able to create new projects using some robust framework, suggesting Symfony2 after making their own research. It was a matter of big projects, thousands and thousands of man hours. Why not?

4. Drupal8 is using Symfony2 components

That was another sign that Symfony is a good choice.
Just like we’ve chosen jQuery or git for all our projects because of the fact that Drupal decided to go with them, and not with mootools, prototype, and mercurial with bazaar. For business needs, it’s almost always good to use mainstream technologies, though it’s not as geeky and cool as writing a CMS in node.js.

5. Our team (and me, mostly) was eager to learn new system after 7 years of (mostly) Drupal development

Oh yeah. The grass is always greener on the other side of the fence, you know :)
While Drupal is moving forward, some stuff in PHP world was still relatively new for Drupal in 2012. (Annotations, composer, twig, …)
And it’s interesting to use this stuff in real project, not on localhost!

That’s it. Now it’s more than a year passed, and you know what?
After two months of work with Symfony (we were building big and complex ecommerce solution), I realized that it will be a big mistake to switch over completely.

Drupal is still a very good choice for 85% of websites in the world. You don’t need high load and ultra flexibility in 85% (probably, 95%?) of world websites.
And Drupal can be a better choice than Symfony2 for all these projects.
The main (the only?) reason is - rapid and easy development in Drupal.

You can create working Drupal website with the speed of prototyping (if you are good Drupal developer with good experience).
Okay, all the hardcore features still require coding, but you can really deliver working stuff in hours, not days of work.
Symfony is good, but it’s a lot more manual work. The good sign of the fact that this problem is real - is the existence of Symfony RAD edition bundle.

I have a good example - right now when we hiring Symfony2 developer, we ask them to build basic website which contains just registration (basic stuff, FOSuserbundle, we ask to remove username field, just leave email and password) + profile (firstname, lastname) + Facebook login (HWIOAuthBundle).

The average time of implementing this by developers is ~7 hours. And most of the time is spent in writing and testing pretty big yaml configurations for bundles.
The same stuff in Drupal will take ~2-3 hours - drupal install, email_registration module, and https://drupal.org/project/hybridauth or similar for facebook login.
So, it’s harder to do “rocket launch” in Symfony.

Some things that are available in Drupal out-of-the-box (like, permission system) are not easy to do in Symfony2. Typically most of sf2 projects contain pretty ugly checks against current user role. And it’s a bad practice comparing to permissions checking - if you use role checking and you need to add another role which can do the same action, you will have to modify code to add this new role.
Of course, you can implement some kind of security voter or ACL in sf2, and it can be smarter and more flexible than in Drupal, but nobody wants to mess with it without REAL reason. And that’s what I call poor engineering - when “right” choices are too painful so most of developers tend to stick to “wrong” choices.

Symfony components

Symfony components (Doctrine ORM, HttpKernel, Forms, Routing, Doctrine annotation parser, …) leave good impression - they are completely decoupled, and it is really a way to go in terms of architecture, not surprising that Drupal8 uses a lot of Symfony components.

At the same time some third-party bundles leave impression that their creators are in love with over-engineering, not in getting things done.

ORM and db queries

Drupal 7 dev team made a lot of efforts to build own ORM-like code for entities (EntityFieldQuery) but Doctrine2 ORM and query builder are far more robust and polished, and play nicely with Symfony models and annotations, this part is really beautiful in sf2 - that’s a no brainer that Symfony is stronger than Drupal in this part.
Writing your own db queries in code is a pleasure in Symfony, and not a big pleasure in Drupal 7, especially if you are writing ‘raw’ SQL - the main reason is that Drupal 7 fields are a victim of own flexibility (they allow you to change single-value field to multiple-value on the fly, and they are also designed for multilingual websites) - and it requires separate table for each field, while in Symfony2 you have to decide if the field is single-value (than it’s a field in a model table) or multiple-value when designing your db structure. Multiple-value field is typically not a field, but a separate model in sf2.
The Drupal 7 approach is good when you use it from admin interface, but not that good when you dig into code, you need three joins against tables with ugly long names like “field_data_field_send_invoice_paid” just to build a condition to check three fields of a node (unless you use EntityFieldQuery, which designed only for loading nodes - so it’s really a performance hit to use it, that’s why it’s not too popular in our code).

Third-party infrastructure

Whole third-party infrastructure of sf2 relies on Github, Composer and Packagist heavily, and it leads to difficulties in tracking which version of the package is good for your installation - for example, some packages can break when you go from Symfony2.1 to Symfony 2.2.
If you still develop in production (ouch!), I bet you will spend a lot of hours trying to understand what to write in composer.json to return your website back to life.
Of course, it happens mostly because Composer and Github were created to make happy everyone in PHP world, not for specific framework.
But for beginner, Drupal module system with 6.x/7.x branches of all modules and themes is way easier to understand.

Another annoying thing is that deployment to production in Symfony2 is significantly more complex than in Drupal.
In Drupal, you commit all third-party modules to single git repo of your project, then you launch git pull, drush updatedb, drush cc on production and you are (typically) good.

In Symfony2, all vendors (third-party modules) are not stored in central git of your project - since most of them have own git repos.
So, when you deploy to production, you need to launch composer install and wait while all packages will update (and your production will be offline during this time).
And if some package git repo is offline - you are in trouble.

Of course, there is a right way to do the deployment - Capifony, based on ruby-powered Capistrano. But you need time and efforts to get used to it.

Code maintenance

But when you’re done with complex project in Symfony2, I would say it’s way easier to maintain it over time, and the code is cleaner and easier to understand by another developer. Though, for me, it’s still not a big joy to write lots of these OOP classes when you are developing stuff. You need time to get used to it.
The fresh example of what I don’t like in sf2:
If you want to output standard translated message “The item was created” to flash (flash is session-stored message, the equivalent of drupal_set_message() in Drupal) you need to put:

$this->get('translator')->trans('flash.create.success', array(), 'JordiLlonchCrudGeneratorBundle');

Good luck trying to type it in without editor shortcuts.

and if you compare it to

t('The node was created successfully');

you probably get the idea of the difference between Symfony and Drupal which frustrates Drupal developers :)
Yes, that’s a global function t() - it’s not super architecturally correct comparing to translator service in Symfony, which you can easily override when you need, but.. I don’t care about overriding translator in every project, but I still use standard translator in every project, and I usually use crud generator, and it’s really a lot of typing!
Every time when I write this, I wonder, if this nice guy, JordiLlonch, creator of CrudGenerator bundle, was thinking about all the developers who will have troubles remembering his name, especially ‘iLl’ part? :)
Of course, you can create your own version of global t() (or extend base controller and add YourController::t function) in Symfony2.
But
1) you will have to do it in every project
2) you will have to explain to your team that there is a non-standard shortcut
3) (in case you do it via global function) you will have this bad feeling that you are going against architecture of your framework :)

Performance

Symfony is definitely not about “we have lean and mean code which is fast”.
It’s about “we have good, a bit bulky, but good-for-everyone architecture and 5 levels of caching, and then we have another level that caches cache of cache”.
Let’s just say that single Doctrine ORM has 3 types of cache.
And you can’t completely disable caching of everything, even in dev environment.
The only reliable way to test configuration/annotation changes is to delete cache every time you modify it.

Symfony2 is significantly faster than Drupal. It implements lazy-loading and autoloading everywhere and it’s nice - memory footprint is relatively small. You can update the memory limit - instead of 128mb (drupal) you can (typically) use 64mb (sf2) for the same functionality.
Doctrine is also relatively fast in production. It is clever enough to make single big update/insert for several objects when you call flush(), instead of ugly multiple node_save which can take lots of time to complete in Drupal.

Conclusion

Symfony2 is more “academic”, OOP, professional and serious, faster in terms of performance, easier to maintain for a team of developers.
Drupal is more fun, less code to write, and faster development and deployment, sometimes quirky, quick, and dirty. It quickly moves to OOP in it’s parts, while other parts are still procedural. That’s what I can call ‘dirty’, too.

The same project will cost roughly twice as much developed in Symfony, comparing to Drupal, and will take twice as much time.
I think the learning curve is approximately the same for Drupal7 and Symfony2.

So, we’re still doing Drupal development now.
At the same time, we were lucky to hire pretty talented sf2 developers, so we now do a lot of Symfony2 projects (5 complex projects so far) and even our Drupal team start enjoying it - but these are still two separate teams, one doing Drupal, one doing Symfony2. And I’m pretty sure that knowledge of Symfony2 will help us when we start doing Drupal8 development - that’s what I call synergy :)

upd: due to good search engine positions spammers seem to love this post, so comments are now disabled.

Comments

Thanks for the refreshingly honest post about your experiences with both! Most posts come from one camp or the other and show some bias, but you dealt with both fairly.

The same project will cost roughly twice as much developed in Symfony, comparing to Drupal, and will take twice as much time.

That seems like a pretty damning quote! Most clients in the web space I've worked with don't consider maintenance when deciding on a project. Maybe short-sighted on their part, but it rarely comes up. Hearing a word like 'double' would instantly remove sf2 from the conversation.

15 October, 2013

Thanks! I agree.
I would say, Symfony2 is (mostly) an area for professional products and custom/highload projects, not corporate/content websites. Though you can develop good content website in Symfony2. Good, and probably expensive :)

16 October, 2013

Agreed - thanks for the honest article, VERY helpful.

There is a use case that may be beneficial to my company – we have a few client sites that are event voting platforms that are simplistic in function but have a high traffic load across a short period of time. They require authenticating the users and processing 1 or 2 simple forms. With these sites the development time is relatively small to begin with and may ultimately save the client money if we could back off on load balanced server resources needed to execute their campaign.

Thanks!

17 October, 2013

The RAD efforts are not a fork and imho they should not be added to core. I have written on this topic at length on my blog http://pooteeweet.org/blog/2205

15 October, 2013

That’s a brilliant post, thanks!
We still like to cut corners :)
I’ve updated my post, removed the “fork” words.

16 October, 2013

Thanks for a thoughtful and well written post. I guess given the costs and time, you have confirmed drupal as the best choice if it's a good fit for the project.

16 October, 2013

Hi,

About I18N, there is a simplier way :

http://symfony.com/doc/current/book/translation.html#book-translation-tags

Inside Twig template, for example :

{% trans %}Hello %name%{% endtrans %}

{% transchoice count %}
{0} There are no apples|{1} There is one apple|]1,Inf] There are %count% apples
{% endtranschoice %}

16 October, 2013

Hi,
the flash message is set just when item was created - so, it’s controller, not template.

16 October, 2013

Ok, indeed in this case this is more verbose than Drupal.

That's the Symfony way. On Symfony 1.x, there were helpers to do this in templates, and you could use them in the controller, but it wasn't recommended.

I think that this is a volontary effort to make things the more explicit as it can be, but believe me, it stays less verbose than Java :)

16 October, 2013

Being a Drupal developer for years I started looking for a framework for projects when client needs more speed and flexibility. I looked at all major PHP frameworks and saw that Symfony is the most solid project in PHP. After spending two weeks with Symfony 2 I was so pissed of with it that I came to conclusion that it will be worth to look at another languages. I tried Ruby on Rails / Ruby and Django / Python and felt in love with the later.

Python's learning curve is pretty much low when you already know one or two programming languages. Additionaly, comparally to PHP you need to type twice less. When it comes to Symfony 2 vs Django comparison... well, no holywar there, but Django is more developer friendly and you need from two to three times less code to accomplish the same task with it comparally to S2. I'm not even talking about the number of libs/packages/apps/whatever you call it: Django and Python have way bigger selection of these.

And the best thing in learning Python is that I started writing better PHP code for Drupal mostly because of a breath of fresh air that Python/Django gave me.

Just my five cents.

16 October, 2013

I completely agree and I should say Python is my favorite language :)
The thing here is that we have lots of projects to maintain, and it’s not me as single developer, it’s a team. So, we decided to stick to PHP for our business needs.

16 October, 2013

Great writeup, Anton!

If I may, it sounds like the summary is "Symfony is more elegant and proper, but Drupal gets the job done." Which means Drupal 8 (rewritten to leverage Symfony Components and follow many of the same "elegance" standards, but not all of them) should be very interesting indeed. :-)

17 October, 2013

the summary is correct, thanks, Larry :)
Drupal 8 will be interesting, indeed. But the transition from d7 won’t be painless for most of contrib, for sure.

17 October, 2013

I can only say, sorry for put my name in the bundle ;) My bundle was a way of learning how create Sf2 bundles. It was an experiment and now some people are using it and I happy of that, of course.
By the way, if someone is interested in how my name is pronunced: /xordy yɒŋ/ :D
Thank you of talk about my bundle :)

20 October, 2013

Haha Jordi :) thanks for the nice bundle!

20 October, 2013

I see this to be a little biased. Some points.

1) If you develop in production? Ugh. Maybe symfony ain't for you if you do that.

2) You need to call composer install not composer update on production, and install is faster than update, since it doesn't have to resolve dependencies and such. In fact, you can configure composer so that it runs all the scripts you need after a deploy.

At the moment, to deploy on some live servers, I do the following: git pull && composer install && app/console doctrine:migrations:migrate

3) $this->get('translator')->trans('flash.create.success', array(), 'JordiLlonchCrudGeneratorBundle'); vs t('The node was created successfully');. Hi unfair comparision. How about $this->get('translator')->trans('flash.create.success');, which is how it'd look if you only have one catalog. Heck, you can, as you stated, add a method to the base controller. And you don't have to do it on all your projects, create your own library which ships the changes you want, and include it. $this->crudTranslationMessage('flash.create.success')

I found the post really interesting, but I wanted to rebate some of the bashing on Symfony2.

21 October, 2013

Thanks for your points!

1) If you develop in production? Ugh. Maybe symfony ain’t for you if you do that.

I do, for projects with small budget and <50h of work. And a lot of people does. Because most of small projects is not about deployment beauty, or good testing, but about getting things done.
That’s what I’m trying to say - symfony2 and “get things done” approach doesn’t live together in small projects (it’s just my humble opinion, based on my experience).

2) You need to call composer install not composer update on production, and install is faster than update, since it doesn’t have to resolve dependencies and such. In fact, you can configure composer so that it runs all the scripts you need after a deploy.

At the moment, to deploy on some live servers, I do the following: git pull && composer install && app/console doctrine:migrations:migrate

That’s right, you do composer install, definitely - it’s my mistake, I’ve fixed the text, thanks!

But all the facts about update still apply to install command:
if you do composer update on dev and then deploy to production and run composer install on prod, you can still break your website if some package website is offline or is just not working correctly for your composer, right now.
If every package in project is on github, and your own repo is own github, your approach can work, that’s true :)

3) $this->get(‘translator’)->trans(‘flash.create.success’, array(), ‘JordiLlonchCrudGeneratorBundle’); vs t(‘The node was created successfully’);. Hi unfair comparision. How about $this->get(‘translator’)->trans(‘flash.create.success’);, which is how it’d look if you only have one catalog.

What do you mean by “catalog” here?
The translation is inside this specific bundle. If you omit ‘JordiLlonchCrudGeneratorBundle’ part in my specific case, you will get ‘flash.create.success’ in browser, not the proper translation.
If you tell me the elegant way to bypass this, I will be happy to try it :)

Drupal t() function is smart enough to find translation from any module, you don’t need to specify module which holds the translation (that leads to performance and other kinds of issues, definitely - but that’s not the point of discussion, since I was talking about code length).

Thanks!

22 October, 2013

1) Indeed, point taken, it's not meant for that kind of projects :)
2) Yes, you depend on github, if you call composer install when deploying. You can build an artifact. By this, I mean a .zip which already contains all the dependencies. Then, just uncompress on prod, and, if your project root is symlinked, change the symlink. Virtually no downtime.
3) The 3rd parameter from the Translator::trans() method isn't the bundle, but the catalog. It's used to prevent collision of translation names.

In drupal, if you have the same text in various modules, but under different context (a translation of a polysemic word), it may mess up with the translation.

22 October, 2013

My deployment to MULTIPLE production servers is as hard as typing: cap prod deploy
All that takes is 20 minutes to setup configuration and production servers.

Ant that does everything.. uploads code, installs vendords, runs migrations, bumps version, etc.

I can't even imagine pains in drupal deployment on multiple machines.

24 October, 2013

You’ll be surprised to know that drush and Aegir can do significantly more than Capistrano and composer, in certain areas. For example, you can setup and run Drupal with your own set of modules just from console - without editing single file.
Try to do it from composer in Symfony2. You, at least, will need to add bundles to
your AppKernel, I’m not even saying about manual configurations of multiple files.

Here is the typical Drupal deployment:

git pull
drush updatedb
drush cc

And you can still use cap which will use drush, of course - since cap gives some good features to your deployment, like maintaining old releases and quick rollbacks.

I’m not saying that Symfony infrastructure is bad, or composer is bad, or Capistrano is bad.
They are very good!
But it’s funny that some Symfony and ‘OOP’ fans think of Drupal like about some stupid ancient procedural set of scripts with ‘@’ error blocking in every line.
I saw some guy writing “Why they don’t just rewrite their Drupal so it’s a bundle” in news about Drupal8 using Symfony2 components. This guy probably assumes it’s like a week of porting.
Drupal is more than that :)
 Peace!

24 October, 2013

Thank you very much for sharing this informative post. The Drupal module ensures that the Symfony Framework module is available to other modules. You should not have to install it unless another module asked you to.

28 October, 2013

Hi :)
I'd like to come back to the following part:

The same project will cost roughly twice as much developed in Symfony, comparing to Drupal, and will take twice as much time.
I think the learning curve is approximately the same for Drupal7 and Symfony2.

Is this true? If you got several projects with Symfony and write own bundles for reoccuring problems (login, content creation, base theme etc.) in which way does it take more time than using Drupal?

I know, as an Drupal Developer, that some custom features can be a pain in the ass to implement in Drupal, mostly due to the "Drupal way". If, after some time, you had such a list of own bundles, ready to use in a new project, wouldn't that kickstart your development?

24 November, 2013

With statements like "The same project will cost roughly twice as much developed in Symfony, comparing to Drupal, and will take twice as much time.
I think the learning curve is approximately the same for Drupal7 and Symfony2" - I wonder if you are factoring in project life cycle (i.e. development over time).

What I've found with drupal is that major version upgrades (on reasonably sized sites on up to more complex with lots of modules) are a complete pain requiring you to essentially rebuild your site. While with a framework, you can likely stay up to date more easily and focus on adding features and improving performance over the years.

While you could argue that this rebuilding time is a good time to rebuild functions, etc. - it also involves essentially spending hours/months rebuilding things that worked fine to begin with.

I think when you factor upgrades and feature additions in over time a framework will likely win for anything but the most basic of sites - and for those drupal if you follow all the conventions is as good as it can be in my opinion.

10 January, 2014

Well, I think that the level of maturity of both systems (Drupal and Symfony) is good enough, and the length of development lifecycles of new major version is so big that most of websites can live happily for 3-4 years without upgrading to younger major version. I have few examples of big projects upgrading from Drupal 5.x to 6.x, and from Drupal 6.x to 7.x, and it definitely requires fair amount of time.

At the same time, I have yet to see any big Symfony 1.x project that was converted to 2.x. The db schema can probably live without big changes, but I suspect the amount of code rewriting will be the same or even bigger here than in Drupal world.

11 January, 2014

That's a great post, thanks!
Right now we have not small drupal 7 project, and I see some serious problems. Looks like impossible to grow. We're using mostly Ultimate Cron, Rules, Entity, Panels, Some modules build custom, and of course we're using views.

For all website tasks we need cron, so..we chose to use Ultimate Cron module and some cron jobs runs every min. I know this is bad practice (very bad for performance), but to accomplish that we need to run cron every min. to check some entity tables..make inserts and updates.

I can tell, we're stuck. Even if we're using Redis caching for auth. users. System slow... Ultimate Cron is killing system. GetPantheon is a great hosting and they give great tools (git, backup, redis, varnish) + great speed, but not for huge projects, my opinion, maybe I'm wrong.

So..why I'm writing all that? I'm trying to reproduce my existing project on Symfony or RoR. Still not sure what to choose.
If someone had tried to move logics and features from drupal in to some other framework, please tell if make sense.. which way is right to use, Symfony or RoR? I'm looking framework with good documentation and for long term to use.

Thanks.

11 July, 2014

Hi Alex!
if you have to run cron every minute - you are probably doing something wrong :)
Ultimate Cron is definitely better stuff than regular cron, though.
But I think you may try to convert this code to queues and workers, you can do that both in Ruby and PHP world - https://github.com/resque/resque is a good example.

Drupal and its node_load is still very expensive in terms of db and cpu. For good performance of authenticated users I definitely recommend to try some framework. We are currently doing several big projects on https://github.com/yiisoft/yii2 which is very fast and looks more like regular PHP - so for our team it is more fun to write code than in sf2 Java-style, but later code reading will not be that smooth I suspect :) the yii2 is not stable yet.

11 July, 2014

Wonderful blog! I found it while surfing around on Yahoo News. Do you have any suggestions on how to get listed in Yahoo News? I've been trying for a while but I never seem to get there! Thanks gedaddgdkfec

05 August, 2014

"Symfony is more elegant and proper, but Drupal gets the job done." is best comment of all time. THX Larry Garfield.

26 September, 2014

Anton Sidashin

Anton Sidashin senior developer, Pixeljets co-founder

I'm a web developer specializing in PHP and Javascript, and Drupal, of course. I'm building Drupal projects since 2005, and I was working as full-time senior engineer in CS-Cart for a while, building revolutionary e-commerce software. In my free time, I enjoy playing soccer, building my body in gym, and playing guitar.

Drupal.org ID: restyler
Drupal association member