7 reasons to switch from Drupal to Yii

Drupal 7 is about to be released, so many organizations need to decide whether to upgrade from Drupal 5 or 6. Drupal is fine if you're building lots of websites and need to create new sites quickly without much coding, or if you just need a blog-on-steroids content site.

Running on Drupal is like living in a double-wide: it's the best solution if you can't afford a custom home. If you have a site that started on Drupal and has grown enough to employ full-time developers, you should consider migrating your site to the Yii PHP framework. (PHP haters can follow The Onion and use the Django Python framework, although it will take more time to change frameworks and programming languages.)

I'm the CTO of a site that switched from Drupal to Yii on April 30th 2010. It was hard to find information when we were debating a rewrite and there wasn't even a book about Yii yet. There were a few comments about switching from Drupal to Yii but they didn't include enough data to reassure me. I was worried that Yii might be slower than our heavily-optimized install of Drupal, so I decided to rewrite the core 20% of our site (which provided 80% of our functionality) in 30 days. It seemed like a great way to test the productivity and performance of the Yii framework, and if Yii wasn't an improvement after that month we could always switch back to Drupal and copy over any new data.

Yii was much faster than Drupal for our site with 150,000 nodes (each with a rewritten URL) and 50,000 visitors per day. Yes, we were working crazy hours for those 30 days (and the following 15), but it was worth it. The time that we previously spent working around Drupal's slow queries was put to better use, and it was a lot more fun to develop on Yii than on Drupal. The real benefit of Yii came later when we redesigned our site. With Yii's MVC, we only had to change 2 layout files vs a few dozen in Drupal.

I just wish we switched a year earlier. Here's what we learned:

Drupal isn't the best way to avoid starting from scratch. Drupal primary selling point to developers is "why roll your own CMS?" Like many developers, I've written entire web applications from scratch (in 1999 and 2000) and appreciated being able to focus on the unique business needs of the application instead of the writing my own code to handle all aspects of authentication, form validation, SQL injection attack prevention, etc. The company I helped found in early 2007 had a prototype website on Drupal, and I was willing to see what Drupal could do before throwing it away for Ruby on Rails. The Ruby craze reminded me of the Java craze in 1997. I was an intern at a WebEx competitor in 1997-99 that killed their performance by coding their server in Java before server hardware and VM optimizations allowed scalability. PHP had proven itself with the Friendster rewrite and at Facebook, and our users didn't want to see a fail whale if we ran into scalability problems with Ruby.



Sure, it's easier to get started with Drupal than coding every line of PHP yourself. But a bunch of PHP 5 frameworks were launched in 2008 and were put to the test in 2009. A PHP developer starting on a web application now (and working full time on only that site) would either choose a framework or start from scratch and use PHP libraries (PECL or PEAR.) If Drupal is a framework, only Rube Goldberg could love it. Drupal is designed to be extensible without much PHP programming. That's fine if you're just styling a simple content site or have little traffic. If you're working full-time writing modules to customize forms and add functionality, you'll spend more time suppressing Drupal functionality that you don't want than you would building on a framework. Yii takes the opposite approach — you can use Ruby on Rails-like ORM if it's fast enough and only optimize the 10% of queries that need hand-coded MySQL. Community-contributed modules are prone to featuritis and the bugs that result from unneeded complexity. There are too many Drupal contributed modules and if you have full-time developers you'll probably just decide as we did to assimilate portions of contributed modules into your own custom modules. Drupal's image resizing-and-caching modules are a great example of this. Because the modules are designed to be generic (so they can work an arbitrary number of other modules!), they include tons of functionality that you'll never use. In our case, we just needed to make thumbnails of various sizes, which the ImageMagick convert binary does. To get that, we had to enable 4 modules, each with a bunch of php files: ImageAPI, the ImageAPI for ImageMagick, ImageCache, and the ImageCache UI. Then the actual commands to generate thumbnails are in 2 tables in the database. If that stops working when you upgrade a part of the chain, it'll take a lot longer to diagnose the problem than if you built only what you needed.



Yii also has an image resizing extension (adapted from the Kohana Image Library), but it is complicated because it is designed to let you easily switch between ImageMagick and GD. (GD has trouble with 2 MB+ images.) Despite all that, it still didn't enable us to resize images on the fly using a RewriteRule if the thumbnail didn't exist. So I created a simple index.php file that just handles RewriteRule callbacks on a dedicated image virtual host and sends shell-escaped commands directly to the convert binary. It means those RewriteRule callbacks don't go through the Yii index.php file, reducing the overhead and time required for image resize-and-cache operations. It's only a page of PHP and the arguments are sent in one call to the convert binary so it's much easier to test and maintain when we upgrade ImageMagick. Drupal has PHP 4 baggage. Once I decided to consider PHP frameworks, I quickly realized I wanted only a 100% strict PHP 5 OOP framework. You don't see many people arguing that Drupal's procedural "hooks" approach is superior to OOP. While Drupal 7 requires PHP 5, like CodeIgniter and other older PHP frameworks it still carries the baggage of backward-compatibility. Who wants someone else's baggage? Don't want Drupal 6 or 7 to slow down a Drupal 5 site? Deal with an outdated jQuery. For most sites that's fine. We really care about speed because Google and Microsoft have demonstrated that users are more loyal to fast sites. In 2009, when Drupal 6 was out and established, we stuck with Drupal 5 because of the measurable speed advantage. The problem is that Drupal 5 includes jQuery 1.0. You can add a contributed module to patch jQuery to 1.2 (and update the Drupal functions that reference it), but that's still an old version. Forget about jQuery 1.3x and Drupal 5. Drupal's field API/content construction kit (CCK) will drive you crazy, and it's part of Drupal 7 core. Why use $node->ip when you can use $node->field_ip[0]['value']. And if you decide that two content types should both have a text field of the same name, CCK will put that in a table of its own (content_field_ip) with delightful column names (field_ip_value). Sure, Drupal can untangle that mess when a full node is loaded, but it isn't pretty to look at in the database. MySQL queries will need many left joins to handle all of the extra CCK tables, and those unnecessarily-complex queries will end up in the slow query log all too often. I finally got fed up with trying to optimize all of these slow queries and decided to get rid of CCK, which is what led me to PHP frameworks, and then to Yii.



Migrating our data to Yii took about the same amount of time as it would have to kick the CCK habit yet stay on Drupal. However, we were able to start with a clean DB without all of the extra tables Drupal uses for its internal purposes. Our old DB had 173 tables; our new one has 54. Drupal is a LOT slower than Yii. Drupal only scales if you cache EVERYTHING with memcached and APC and rewrite all slow queries. Caching is especially important if you use SEO-friendly rewritten URLs for all of your links because each l() function is a separate database call. So an average page has 50+ queries on it, versus 3-5 in Yii. After switching, our average page download time decreased from 162 ms to 67 ms according to Google Webmaster Tools. Even better, Yii + APC is so fast that we haven't needed to use memchached, simplifying our code and operations.

Our server stats speak for themselves -- for the same number of simultaneous visitor requests (Apache processes), the DB and CPU utilization went way down. Memory use remained about the same. Over the last year, our traffic has increased 60% to 1.5 million monthly visits while MySQL queries have fallen by 66%