Comparing Laravel, CodeIgniter, & CakePHP

Today I received a comment on my Laravel Auto-Generating Named Routes post that I felt deserved its own post.

Matthew Schenker wrote I see you’ve worked with CakePHP and CodeIgniter, and now you’re mentioning Laravel. I’ve been happily using CodeIgniter for a while now, but lately I see a lot of people mentioning (and loving) Laravel. I’m not looking for one of those “which is best” answers. Long ago, I learned that this is not a good way to look at various frameworks. But I’m curious — what are your general impressions when comparing these three frameworks?

CakePHP, CodeIgniter, and Laravel are all great frameworks in their own rights. They each have their pros and cons which I will cover here. Bear in mind that these are my opinions and forming your own by messing a bit with them is always the best policy. And as mentioned in Matthew’s comment, this is not an “OMG FRAMEWORK X IS TEH BESTEST!!!1!” post.

CakePHP
Cake, if I recall correctly, was one of the first PHP frameworks around back when spaghetti code was standard. The idea behind Cake was to make developing applications fast (ie, “convention over configuration”) by cutting down on how much code the developer needed to write. Less time working means more time making money.

Pros

  • Built-in ORM which I’ve always really enjoyed. I really like how the results are in $post[‘Post’][‘field’] format. Building queries is really simple and you can fetch (for example) a blog post and all of its comments in one or two lines of code.
  • Reverse routing. This makes maintaining links in an application so much easier. This means if you change a controller’s name at some point, instead of search/replacing 200 instances of “admin/foo” with the new “admin/bar” (and hoping you didn’t miss one) you simply update the route in one place. Any links using the reverse route array will automatically point to the right spot at runtime.
  • Big community. Because Cake had been around so long you can find the answer for pretty much any question you come up with. If you can’t? They have their own website where you can submit questions, as well as (I believe) a mailing list.
  • Plugins. This makes re-using code super simple and help keep the app folder clean (if, for example, you are distributing an app that uses modules).

Cons

  • Incredibly slow. Recent versions of Cake (2.2.x as of this post) are much faster and more efficient than previous versions, but  it is still one of the slowest frameworks. I am personally not sure how well it holds up when an app of it gets slammed with tons of hits. I am aware that Mozilla’s plugin site runs on an (old) version of Cake, as does Cake’s own bakery and Q&A sites, which all seem to run fine. I suspect it’s a balance between caching and server fine-tuning.
  • TONS of lines of code. Some developers don’t care what’s going on under the hood; I like to be able to quickly find out how/why something works the way it does. The code is well documented but there’s just so much of it it can be overwhelming.
  • Occasionally, you need to use code to reign in just how much it does. For example, my first step is to open my AppModel and set $recursive = -1 and adding Containable to Behaviors to prevent it from auto-grabbing related models and letting me tell it what I need.
  • Autoloading can be awkward. In recent versions of Cake they’ve introduced lazy loading in the form of  App::uses. Then, if you need to have access to (for example) the Model class, you do something like App::users(‘Model’, ‘Data/Model’) at the top of the file. This is, IMO, clumsy and no better than doing a require CORE_PATH.’Data/Model/Model.php’;

Conclusion: Personally, I use Cake if I need to put together a dynamic site quickly that I don’t foresee getting a lot of hits (like for a local restaurant, for example).

CodeIgniter
I’ve mentioned on here before that CI was the first framework I ever used and helped me finally understand the concept of OO programming. It’s certainly popular, and has been around a similar amount of time as Cake.

Pros

  • Super easy to set up and use. This makes the entry level for a newer PHP developer much lower.
  • Extremely well-documented, with examples in a lot of places to illustrate usage.
  • Extremely fast.
  • Huge community. As with Cake, since CI has been around so long you can almost always find your answer via Google, CI forums, or their IRC channel. This also means there’s lots of code contribution to help get things done (like Paypal libraries, etc)
  • Sparks, the “hub” where CI packages go to hang out and be used.

Cons

  • No modular separation by default. This is a big deal for me as I prefer keeping my code as separated as possible. There is Modular Extensions, which does the job, but I’ve never been 100% satisfied with it.
  • Since 2.x broke CI has been 5.1.6+ for its minimum PHP version, but the whole $this->library, procedural function helpers, and extending a class by prefixing MY_ in front of it way of doing things just doesn’t work well for me. Perhaps this will change in 3.0? *shrugs*
  • I personally have to extend way too many core files to get CI working the way I like it. The more you modify the core, the more you have to maintain later. I’d rather be coding something productive.

Conclusion: CodeIgniter is a fantastic framework for getting the hang of PHP and OO coding and for knocking a small site together fairly quickly with low overhead.

Laravel
Laravel is still in its early days compared to the “grandpas” of the framework world (I believe it was first introduced in 2011), but it has already gathered quite a following.

Pros

  • Modularity is built in via “bundles”, making it really easy to drop in/reuse code across application
  • Eloquent ORM is a simple, super fast ORM that makes working with database relations easy
  • Very configurable and extendable. I can set up apps with the folder structure the way I like it and how it works best for me.
  • Blade template engine. Very fast (compiles to PHP then caches the results) and very extendable. So easy to add new features without hacking the core.
  • Artisan (CLI). Before I started using Laravel I had zero use for CLI tools like migrations and tasks. It’s so easy to create both of those things with Artisan that I can’t believe I waited so long to try it out!
  • Reverse routing!
  • Excellent documentation.

Cons

  • It’s still quite new which can mean some instability with the code. However, since 3.x’s release (and certainly since 3.2.x’s, the most current as of this post) this has slowed down quite a bit.
  • Laravel’s core files are all within (at least) the Laravel namespace and not all of the files in core use a namespace slash ( a \ ) in front of a call to another core file, which makes extending some classes a bit trickier. This is not a huge issue and one not every developer will need to worry about.
  • Routing can feel a little odd sometimes. In my dynamic controller routing post I showed the workaround I used to dynamically route to an add function in any controller. I have not dug deep enough into the semantics of Laravel’s routing methods to understand why such a workaround is necessary but it does add another layer of complexity, IMO.
  • Because of its newness the options for finding answers are still limited in comparison to CakePHP and CodeIgniter. However, the forums and IRC seem to be quite active with helpful people, so usually the answer is findable.

Conclusion: Laravel is currently my framework of choice. Its coding style meshes the best with my own which makes developing much quicker for me.

So there you have it! A personal comparison of 3 big players in the PHP framework world. As always, the best framework for you is the one that you code best in. The “Cons” foreach 😉 framework are my personal beefs with each of them and should be taken with a grain of salt. The best advice I can give is to try them each on for size and see which you like best.

Extending CodeIgniter’s Database Forge Class

UPDATED 2/13: Added License (MIT) Info to code
UPDATED 1/13: Changed ‘required’ ‘required_once’ to avoid errors of redeclaring CI_DBforge

I am working on a project in CodeIgniter that requires use of the database forge class to create/modify/delete database tables. Because the project makes use of database transactions, creating tables with the MYISAM engine was not going to work. So I was faced with two choices: Make all the database creation, etc run by manual queries such as
CREATE TABLE `blah`...
or extend the dbforge class. After some tinkering about I finally managed to successfully do this. Here’s how:
(Note: I am using CI 2. This also assumes you are somewhat familiar with extending CI classes)

  1. Create a MY_Loader.php file in application/core (or open it if you already have one).
  2. If you had to create the MY_Loader file, paste the following:
    <?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
    class MY_Loader extends CI_Loader {
    }
  3. Paste the following in your MY_Loader file:

    /**
    * Extend the Database Forge Class
    *
    * @access public
    * @author (Original) EllisLabs / (Extension) J Elmore
    * @license MIT
    * @version 1.0
    * @return string
    */
    function dbforge()
    {
    if ( ! class_exists('CI_DB'))
    {
    $this->database();
    }

    $CI =& get_instance();
    $class = 'CI_DB_'.$CI->db->dbdriver.'_forge';

    require_once BASEPATH.'database/DB_forge'.EXT;
    require_once BASEPATH.'database/drivers/'.$CI->db->dbdriver.'/'.$CI->db->dbdriver.'_forge'.EXT;

    if( file_exists(APPPATH.'database/drivers/'.$CI->db->dbdriver.'/'.$CI->db->dbdriver.'_forge'.EXT) ) {
    require_once APPPATH.'database/drivers/'.$CI->db->dbdriver.'/'.$CI->db->dbdriver.'_forge'.EXT;
    $class = 'DB_'.$CI->db->dbdriver.'_forge';
    }

    $CI->dbforge = new $class();
    }

    This basically adds the code to find/include the extended class, and instantiate it

  4. Next you need to create some folders in your application directory. First, create the folder database. Then, within the database folder, you’ll need to create a drivers folder. Within the drivers folder you’ll need to create a folder for the database type (mysql, mssql, etc) you are using. Since I am using MySQL, I created a mysql folder. My folder structure, then, looked like this:

    application/
    -->database/
    ----->drivers/
    -------->mysql/
  5. In the driver folder you created (in my case, the mysql folder), create a file in the format _forge.php. In my case I created mysql_forge.php.
  6. Create your extended class:

    <?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
    class DB_mysql_forge extends CI_DB_mysql_forge {
    }
  7. Have fun extending the functions! To get my tables to specifically create with the InnoDB engine I used the following code:

    /**
    * Modify _create_table to use InnoDB
    *
    * @access public
    * @author (Original) EllisLabs / (Extension) J Elmore
    * @license MIT
    * @version 1.0
    * @return string
    */
    function _create_table($table, $fields, $primary_keys, $keys, $if_not_exists)
    {
    $sql = parent::_create_table($table, $fields, $primary_keys, $keys, $if_not_exists);

    $sql = rtrim($sql, ';');
    /* Should note here that I have a custom config file with the key/value pair to hold the
    default database engine to use */
    return $sql.' ENGINE='.config_item('database_engine').';';
    }

I tried simply extending the dbforge class but since all the magic happens in the driver classes it was necessary to extend the driver and modify the functions there. Also, I know there are ways to set the mysql server to default to InnoDB creation but since this project may be sold/released at some point it is easier to modify the CodeIgniter files than to try and provide instructions for something most people wouldn’t be able to or know how to do.

Kohana 3 & CodeIgniter 2

For the last month or so I’ve been developing an app side-by-side with Kohana 3 and CodeIgniter 2 to see which framework fits my programming style better. Nothing terribly fancy; just a simple CMS.

I’ve been using frameworks to develop since 2006, back around CI 1.5.x. The differences between CI 1.7.x (the latest version as of this post) and CI 2.0 are negligible. My biggest nitpick comes with the helpers. I’m lazy and I’m also somewhat speed-conscious, which means I either need to autoload all the helpers my app needs in the autoload.php file (or early in my app) to appease my laziness, or load them as needed to appease my speed-consciousness. It irritates me that they’re basically files holding groups of procedural functions and if I want to access the CI super global I have to instantiate it in every function.

I started dabbling with Kohana a couple of years ago, in the 2.3.x era. I really loved their use of static functions (I’d only had basic OOP experience at the point), but I just never felt comfortable with the way things changed so much between versions. Last year when v3 was announced I had a look through the code and said “forget it”. But eventually I became curious again and started learning it to see how easy/hard it was to develop with it. I personally did not have a lot of trouble learning Kohana 3, between the user guide and the unofficial wiki. Perhaps my biggest stumbling block came with the Database module, which was a complete change from any of the v2.x database classes.

I really didn’t find either framework harder than the other to code for. I was able to more or less figure out how to do what I wanted to do in both. Yes, Kohana’s docs suck and CI’s are much better. For me it wasn’t much of an issue.

In the end it comes down to framework stability for me. And in this case, CI wins, hands down. Don’t get me wrong; Kohana is beautifully written and introduced me to a prime example of clean, well commented code. The devs are extremely intelligent and more talented than I’ll probably ever be. CI is also very clean, though there’s a bit more hacking involved for me to get it to work the way I like. However, I don’t want to be writing my own clean, well-commented code for one version of a framework only to find out the next version is going to totally break backwards compatibility. The lead Kohana devs have stated that there are no guarantees of stability between major versions (ie 1.x-2.x, etc). Comments like “well if it ain’t broke, don’t fix it” are dandy, but if part of the reason I’m using a framework is to let someone else worry about the basics for me, why would I stick with something that is no longer actively developed because the devs are on version 342.x?

While I respect progress and not letting code stagnate there’s something to be said for code stability when you’re maintaining a framework. Uber-optimising something is great (as there are repeated mentions of “x function is faster than w function” in the Kohana forums) but if it’s only saving me 0.02 ms of page load time or 0.25 mb memory, I’m not sure unstable code is worth that bit of extra speed. Furthermore, using an older codebase when you’re a one-(wo)man show can be a nightmare, since it’s a lot easier for one person to miss something than two, whether it’s a simple invalid method call or a glaring security hole.

I want to create apps to earn a living and I want to know that my code will stay more or less relevant between framework versions. API changes are to be expected between versions but complete rewrites, with very little thought for BC is just poor project management, IMO.

Please bear in mind that these are simply my views on the frameworks and my experiences and since I’m not a BDFL PHP guru (or something), you should perform your own research to see what works for you.

Update: I’ve posted a follow up post with some more thoughts (and such): https://nerdmom.wordpress.com/2010/08/31/a-follow-up-on-kohana-3-codeigniter-2-the-flip-side/

Just a couple of updates

I am still working on my OMGSUPERAWESOME project, although I hit a stumbling block and have spent the last 3 or 4 days tearing my hair out.

I mentioned how I had started developing with Kohana. Everything was working well (for the most part)….then I read a post from one of the lead developers that Kohana 3.0’s code would most likely be incompatible with 2.3.x’s. Apparently this is fairly common with Kohana, and I suppose depending on your point of view it can be a good thing or a bad thing. For me this was very bad.

Maybe I’m just stubborn but I like the tools I’m working with to remain somewhat stable between versions. I don’t want to be told that the code I’m writing now will have to be completely reworked to work with the new codebase. That’s a humongous waste of my time, and any users that may be using my software.

So I was playing with the idea of going back to good ol’ CI, but I gotta say — I really did not relish having to go back to writing 2 to 3 times as much code just to get a semblance of the functionality offered from Kohana or one of the other frameworks. Maybe I’m lazy, or maybe I’m just looking to increase my productivity. Maybe both.

So I started playing with CakePHP again, and spent the better part of last Sunday measuring the difficulty of setting up the MVC for a fairly straightforward part of my app. It wasn’t as hard as I was afraid it would be so I continued working with it and slowly have become more impressed with it.

I’m still a little hesitant to say for sure that I will end up sticking with Cake; I’m concerned that if I release my app and someone has an issue that isn’t directly related to my code (ie, it’s an issue having more to do with Cake) it’s going to be a lot harder for me to track down since I’m not as familiar with Cake. I’ve “made up my mind” that I was just going to say **** it and go back to CI only to remember why I was so frustrated with CI in the first place. On the other hand, Cake is a lot more rigid and I find that I end up bending my app around it, whereas with CI it’s more of a silent partner. Of course, with CI it’s pretty easy to end up with a lot of spaghetti code.

Suffice it to say I haven’t definitively made up my mind yet. *sigh*

Frameworks Part Trois (or, Sometimes when you're right, you're wrong)

Yesterday I posted about my experience trying out CI, Cake, and Kohana side by side while I work on my super-cool-blah-blah-blah idea. I mentioned how I was unable to retrieve lists of things with Cake and Kohana, and how quickly I got through things using CI + DataMapper.

Well, Houston, we hit a problem.

Last night I realized that DM was not encoding passwords before inserting/updating them in the database. I ended up changing it to just encode the posted password value and insert (not an ideal solution, IMO). This morning I was making a few other changes and running some tests and I realized something huge.

DM was not validating any of the data.

Obviously, this is a HUGE concern, and not one I was particularly interested in trying to track down and fix. On a whim I decided to give Kohana one more try, and holy [expletive] am I glad I did.

I have no idea what I was doing wrong yesterday with the ORM library but today it’s been working flawlessly (knock wood). It’s validating things the way it should, inserting and updating the way it should, and (hopefully) will help maintain the relationships the way it should.

As far as the rest of the functions and such, it was extremely easy to switch things from CI to Kohana (the fact that I’m only about 4 files in helps ;)). I’ve been able to find/figure out pretty much everything from the docs on their site and a little googling.

At this point, assuming the ORM continues working the way it should, I feel pretty good that I’ll finish up this project with Kohana.

Side note: I found a module at projects.kohanaphp.com that’s called “Debug Toolbar” and it’s pretty sweet. It shows execution time, memory consumption, all db queries, and other nerdy goodies for the developer to use. It sits at the top of the browser, out of the way, and is slightly transparent. Cool stuff!

Frameworks, My Opinion Part Deux

Earlier this week I had a super-awesome-omg-eureka idea for a program. This idea was so hot that I put the forum project on the back burner so I could concentrate on this new idea – something I never do.

As I’ve mentioned here before, I love CodeIgniter. It’s fast, it’s simple, and it’s flexible. However, I decided for this project to try my hand (again) with CakePHP and Kohana, sort of creating side (CI) – by side (Cake) – by side (Kohana) to see which I was able to develop with faster.

For CI, I used CI 1.7.1 with DataMapper for ORM capabilities.
For Cake, I used the latest 1.2
For Kohana, I used the latest 2.3.1 and utilized the ORM library

Now, I was well aware that I would need to reference a lot more for Cake and Kohana, since I only had passing experience with them.  My biggest focus with them was database interaction since this app is database-driven.

I’m still pretty new to ORM, and perhaps there was something I missed, but I absolutely could not get a list of records using Cake or Kohana. I followed the docs on their respective sites and even copied a couple of examples (changing tables/fields as needed), and still nothing. I’m not sure if it’s just me but Kohana’s ORM find_all function does not seem to work at all. The only result I got was “Resource id #31”. Googling both frameworks for some insight brought me no definitive solution. I worked for nearly 3 hours on each to get a complete controller functioning, and only got as far as the C and the U.

On the other hand, using CI + DataMapper, I had a complete controller with all functions – C, R, U, and D – ready to go in less than an hour, including time to reference the DM manual.

I was also less than impressed with Cake’s atrocious loading times. I loaded the same controller from each framework, and my results were CI: 0.348, Kohana 0.83, and Cake 3.29. That means on my (admittedly lower-spec) server, it took 10x as long for Cake to load as CI! I’d hate to see the load times when the entire app was up and running :-\

I guess for now I’ll be sticking with CI + DM. If Kohana can get their ORM library fully functional I’d give them a try again; I will admit that I felt Kohana was more flexible in certain areas and allowed a bit more fine-tuning, as well as having some features that CI doesn’t (Auth, Payment modules).

forum update part deux

I am more or less finished with the first draft of the forum. The nuts and bolts of the program are there (not highly polished but that’s what second/third/fourth drafts are for), and I am feeling pretty good about things.

Originally I was going to use a simple, hard-coded usergroup method to handle permissions for the forums. However, when I wanted to start adding permissions such as ability to view profiles, users online, ips, etc, it became a LOT harder to use the simple, hard-coded method. So I ended up creating somewhat of an ACL (access control list) for usergroups, which is working out pretty nicely. I combined the ACL (which is stored in the database) with some database caching to cut down on queries and it seems to work pretty well.

So far the hardest part has been syncing everything to work correctly — updating thread reply numbers when a post is created or removed, for example. You look over everything before testing it out and there’s (almost always) one little glitch that managed to sneak in there. So you fix it, then go back and reset the database (because apparently your program felt he was being a nice chap by updating what it could) and try again.

I am now on to rewrite #1. I am going to try my hand with Object Relational Mapping this time. I am hoping it will help speed up the CRUD-writing and make maintenance way easier — 2 things that ORM seems to offer, from all the research I’ve done. For anyone who is interested, I’ll be using DataMapper.

So – here I go! 🙂

Hee

While working on the remove_user function, I have a variable entitled $thread. I need to find the number of rows for the $thread query, and without thinking labeled that one $thread_count. 😀 The kind of humor you would probably only appreciate if you buy your own sheets.

Forum Update

Well, I’ve been working on my forum for a week now, and so far this is what I have done:

  1. Create/Modify/Close/Open/Delete Categories/Forums with per-forum permissions for each usergroup
  2. Create/Modify/Ban/Unban/Delete Users
  3. User Registration & Login
  4. Create New Thread
  5. Modify/Move/Delete Thread (for those with sufficient permissions)
  6. Reply with BBCode and Smilies
  7. Quick Reply with BBCode
  8. Modify/Delete/Restore Posts
  9. Integrated Smarty with Layout Capabilites

Phew! It’s kind of nice to see that I actually did get a lot done; truthfully I keep wondering if I’m wasting my time with this when there’s so many other forum scripts out there that have a team of people behind them.

Another neat thing I did was port CI’s form helper functions to Smarty functions so I can use things like

{form_open url="controller/function" id=$id}
(The id is if I’m modifying something; it appends the id to the action url)
and
{form_input name="field_name" value="submitted_value" default="default_field_value" extra="usually_css_here"}

If anyone is interested in having a copy, let me know in the comments and I’ll attach the functions I have. Currently includes form_open,form_close,form_dropdown,form_input,form_hidden. In addition, I ported the anchor and link_tag helper functions.

There’s still so much to do I wonder if I’ll get it done. I’m pleased with the progress so far, and if nothing else I am learning a lot 😀

Super duper easy Code Igniter + Smarty WITH layout capabilities!

I’m deep in the midst of the forum I’m creating (more updates about it to come later) and I decided to implement Smarty into it since I’m considering releasing it for distribution at some point, and my target users would definitely be more comfortable with {$var} than <= $var; ?> or <php echo $var; ?> .

The one thing snagging me was how to incorporate a layout so I didn’t end up with 100+ template files that had the {include file=”header.tpl”} in them. Definitely a PITA and not that great if you want more flexibility.

With a little bit of trial and error, I created a library that is less than 50 lines long, works awesomely with Smarty and supports layouts.

Instructions
1. Download the latest version of Smarty from http://www.smarty.net
2. Extract the /libs folder to your application/libraries folder and rename to smarty
3. Open your favorite text editor and put the code found @http://codesnippets.joyent.com/posts/show/1966 into it.

Save as Template.php in your application/libraries folder. In the __construct() function, change the paths to suit your application. For me, I chose to place my templates folder above my application folder, and the other folders within the /smarty folder. You can also change the template extension in the layout function to something other than .tpl, if you like.

3b. If you want to load this application-wide, open up your config/autoload.php file and add “template” to the libraries array.

4. Next, create a default.tpl (or default.html, etc) file and where you would like the content displayed, put the following:
{include file="$inner_template.tpl"}
(again, you can change the tpl to something else if you wish). Save this to your templates folder.

5. To use, load the template library and then use it like so:
$this->template->layout("content_template", array("array"=>"of stuff","to"=>"use within the template"));

6. If you want to use a different layout for part of your app, simple include the following line before calling the $this->template->layout function:
$this->template->theme = "other_layout_name";

There may be better ways to do this, and I know a lot of programmers absolutely loathe template engines and will argue til the sun comes up that they serve no useful purpose and everyone should stick with pure php. However, this particular method is working very well for me and my program 🙂