Transitioning from CakePHP to Lithium
For anyone following the CakePHP project, you likely already know about the Cake3 project spinning off and becoming a separate framework called Lithium
For anyone following the CakePHP project, you likely already know about the Cake3 project spinning off and becoming a separate framework called Lithium. After a couple of months of testing the Lithium framework and using it for my current web development needs, I’m so encouraged by the experience and the results, that I had to suggest to my readers that they consider making the transition from Cake to Lithium.
For anyone following the CakePHP project, you likely already know about the Cake3 project spinning off and becoming a separate framework called Lithium (li3 for short). After a couple of months of testing the Lithium framework and using it for my current web development needs, I’m so encouraged by the experience and the results, that I had to suggest to my readers that they consider making the transition from Cake to Lithium. As the framework nears its 1.0 release, I expect the core feature set to include all of the essentials that we Cake users already enjoy, but with some significant improvements. For those that appreciate good code like good art, Lithium is clearly a step in the right direction.
So far, I’ve only had occasion to try out a few features, and the outcomes have already been promising. Here are differences I’ve picked up from how things are done in Cake.
Bootstrapping and Additional Libraries
Lithium’s way of bootstrapping the various libraries allow for various server configuration settings more easily than Cake. Rather than defining constants in the app/webroot/index.php file, server paths are stored in the app/config/boostrap.php file. Only two constants need changing if you adjust the folder structure on your server: LITHIUM_LIBRARY_PATH, which points to the core libraries directory, and LITHIUM_APP_PATH, which points to the application itself. Other core settings may be included in bootstrap.php; as good practice, I added
ini_set('display_errors', 1); Lithium uses third-party libraries much more seamlessly than Cake. Before, the scripts would have to be included through a vendors folder and brought into the application using, essentially, an include-like function. What I had wanted was a little more flexibility for where third-party scripts could be stored, since the possibilities for what third-party scripts require, in terms of server configuration and installations, usually call for install paths very different from how Cake structures itself in the background. Lithium provides a configuration file, app/config/boostrap/libraries.php, which allows you to add libraries either with a require directive or by using its built-in Libraries class. I was able to drop the Doctrine ORM library in the app/libraries directory and bring it into my app with:
Libraries::add('Doctrine', array( 'path' => LITHIUM_APP_PATH . '/libraries/doctrine/DoctrineORM-2.0.0/Doctrine' )); Easy enough!
Namespaces and MVC
How Lithium makes use of PHP 5.3′s namespaces improves the flexibility of building model and controller classes. In one app, I have a sheet music database that provides downloads to web users. On the home page, it provides a list of all the composers in the database and a list of the top ten most downloaded files. In Cake, to do this, the ComposersController class has two options to fetch those top ten downloads. One is to perform a requestAction call to the DownloadsController class. The other is to call its own model class and perform a bindModel on the Download model, then run a find method to pull the top ten downloads. This isn’t too difficult or bloated, code-wise, but notice how Lithium improves upon this scenario.
I simply add:
use app\models\Download; to the ComposersController class, then run the find method like so:
$downloads = Download::find('all', array('orderBy'=>'Download.downloads DESC', 'limit'=>10))->to('array'); One advantage here is that I don’t have to directly instantiate the Download model class in the controller; I simply call its namespace with the use method, and all of its methods are available to the controller. I don’t have to worry about table associations if I don’t want to. And, well, the code just feels cleaner and yet still adheres to the MVC paradigm that keeps the various classes abstracted from one another.
When it comes to Lithium’s console, it’s just a fun piece of work, and much easier to implement than Cake’s Bake script, in my opinion. Because Lithium makes more direct use with its li3 console app, the integration with your application comes pre-built and ready to go. What I’ve always appreciated about Ruby On Rails and Symfony is their use of the console to automate development processes. But I’ve also admired Cake for not being overly tied down to the console that you must create a particular shell environment to get the framework to install easily. In fact, in my earliest days of web frameworks experience, this factor pulled me over to Cake in the first place; I had spent hours trying to get Symfony to run correctly in my local console environment, but Cake just worked after dropping the main folder into my server root. I didn’t care what core features Symfony offered at the time because I could get right to work in Cake without any headache.
Lithium, on the other hand, improves upon both of these paradigms of console development, if you ask me. It maintains the same drag-and-drop installation capabilities as Cake, but comes packaged with console features that rival Ruby On Rails and Symfony. (I realize, though, that I’m speaking of a framework that is currently at 0.6, so some of this is my own predictions of what will come through at the 1.0 phase.)
Getting li3 to run required a simple adjustment to my .profile file. I simply added:
export PATH=/usr/lib/lithium/console:$PATH to my .profile (I have the Lithium core installed in my /usr/lib directory) and was able to call li3 in the terminal, and was in business. After following the Console Tutorial on the Lithium site, I had a numbers game up in minutes. In short, I created my own console class in the app/extensions/command directory and then ran it quite easily by pointing to the application with cd, and from there calling li3 numbers (numbers was the name of the console class). I didn’t have to add any flags to the command line, just simply browsed to the app folder, and li3 knew what to do from there. Now, obviously the numbers game is a trivial way of learning the capabilities of a shell environment for a framework. But the integration is such that I’ll be able to customize console commands to perform unit tests, populate the datasource with schematics, manage sessions, perform cron jobs, build custom classes automagically, and so on.
I’ll admit that the hardest chapter to write for my Beginning CakePHP book was the one on datasources. This was simply because the documentation was sparse on even how to get datasources working, let alone explain a normative way for optimally doing so in the Cake environment. Since then, the documentation has gotten much better. Nevertheless, the datasource schema for bridging various sources favors a kind of database model, meaning, you still use the $useDbConfig property and define that value in the config/database.php file to attach a datasource to your Cake app.
Lithium, on the other hand, assumes wildly different ways of sourcing data to your app. In fact, it comes pre-built to handle cutting-edge datasources like MongoDB and CouchDB which require a little more flexibility to leverage their feature sets. It handles these sources not as databases per se, or as PDO abstractions, but as connections. This semantic difference actually amplifies the capabilities of the datasource structure because it further abstracts the way data is pulled, manipulated, and otherwise handled by the framework. Web services like the dozens Google and Facebook applications are providing all could interact with a Lithium app the same way a database would, without attaching duct tape here and there in your code base. This makes for leaner code, and above all, improves performance significantly.
Dedicating two months to Lithium after years on the CakePHP platform has made me a convert for one basic reason. In the end, they both will get it done, and will get it done well. But, to be honest, the experience feels different, and however else the pieces fall into place that make the two frameworks semantically and structurally different doesn’t really matter when push comes to shove. As a developer, I just want to enjoy coding and I want it to be lean and clean.
So it really has begun to feel a lot like my experiences on the Mac and PC platforms. On the one hand, the Apple paradigm fights vigorously to streamline the feature set and to zero-in on each feature as a unique contribution to the user experience. They are ready to scrap features if they have to in order to maintain an intuitive and clean experience because they know that in the end, the user has to come away with a positive and simple interaction with their software. But the Microsoft paradigm has always been one of amplifying the feature set as much as possible and creating a platform that cannot be brushed aside. They want to drag-race the competition and compete as a total platform, one that out-does everyone else’s feature set, though only recently are they working harder to focus on the user experience. (Check out The Marketing Playbook by John Zagula and Rich Tong for a detailed explanation of how Microsoft thinks about platform plays behind the scenes and demolishing competition through Windows integration.)
Cake has started to feel less clean and more like Zend Framework feels; chock full of features, but lacking in performance and rigorous streamlining of the core feature set. I give kudos to Garrett Woodworth, Nate Abele, Joel Perras, Alexander Morland, and David Persson for their vision for Lithium and encourage you to give their new rising-star framework a go.