Sunday, April 6th, 2008...9:58 pm

A Review of CakePHP

Jump to Comments

CakePHP Logo Recently, on a somewhat secret project, I’ve had the opportunity to try out CakePHP, an MVC framework for PHP. I wanted to take some time to share my thoughts on what I’ve liked and disliked in my experience so far.

Missing Migrations

My #1 favorite feature in Rails has to be migrations. They allow you to very easily add and remove fields of a database without trying to keep track of SQL queries. In CakePHP, nothing like this exists (at least that I’m aware of). I’ve already had numerous issues with databases being out of sync due to having the code in three different environments (dev, staging, and production). I’ve had to resort to a combination of phpMyAdmin and text files with SQL to keep track of all the changes that need to be made.

Models Fall Short

Personally, I’m a huge subscriber to the “fat model, skinny controller” method of structuring code, which stipulates that the majority of code should reside in your models (which handle the data), rather than the controllers and views. With CakePHP, however, this is a little difficult to implement. When querying the database using a model like $this->User->findAll();, the function just returns a text array, rather than an array of objects like Rails does.

To demonstrate my point, let’s pretend I have a table of users that stores their first name as first_name and last name as last_name. I want to print out their first name, last name, and their full name (which is generated from their first and last name). With Rails, I just add the method User#full_name to the User model. Since the full object is passed to the view, I can call that method directly:

First Name: <%= @user.first_name %><br />
Last Name: <%= @user.last_name %><br />
Full Name: <%= @user.full_name %>

However, with CakePHP, since it’s only an array that’s passed, I can’t call a function, and the code gets a little messy:

First Name: <?php echo $user['User']['first_name']; ?><br />
Last Name: <?php echo $user['User']['last_name']; ?><br />
Full Name: <?php echo $user['User']['first_name] . ' ' . $user['User']['last_name']; ?>

Granted, I could use a helper function in the view, but in my eyes, generating the full name is something that should reside in the model. In this example, it’s really not that big of a problem, but as you want to do more complicated manipulations of the data, it gets a little messy with CakePHP.

Messy Syntax

While it isn’t totally the fault of CakePHP, but rather of PHP itself, Cake requires some pretty messy syntax to accomplish things. For example, let’s say I have posts that have both an editor and an author. To define these relationships in Cake, I’d have to do the following:

// user.php
class User extends AppModel {
  var $name = 'User';
  var $hasMany = array('EditedPosts' => 
                        array('className' => 'Post',
                              'foreignKey' => 'editor_id'),
                        'AuthoredPosts' =>
                         array('className' => 'Post',
                               'foreignKey' => 'author_id')
                      );
}

// post.php
class Post extends AppModel {
  var $name = 'Post';
  var $belongsTo = array('Editor' => 
                          array('className'  => 'User',
                                'foreignKey' => 'editor_id'),
                         'Author' =>
                          array('className'  => 'User',
                                'foreignKey' => 'author_id')
                        );
}

Pretty confusing, huh? All the arrays really get in the way. In Rails, the same situation would be done like this:

# user.rb
class User < ActiveRecord::Base
  has_many :edited_posts,   :foreign_key => 'editor_id',
                            :class       => 'Post'
  has_many :authored_posts, :foreign_key => 'author_id',
                            :class       => 'Post'
end

# post.rb
class Post < ActiveRecord::Base
  belongs_to :editor, :class => 'User'
  belongs_to :author, :class => 'User'
end

To me, the Rails code is a lot easier to read and makes much more sense. Like I said before though, this is really a Ruby vs PHP issue and not Rails vs CakePHP.

Super Easy Deployment

It may seem like I’m really ragging on CakePHP, but there are definitely things I like compared to Rails. One of my (and many others’) major gripes about Rails is how difficult it is to deploy an application: there’s a lot of server side configuration that can get really confusing. With CakePHP, however, it’s practically a non-issue. Since that supports PHP (which I’m guessing is 99% of shared hosting). Just upload your files, and you’re ready to go. With Rails, setting up a production environment would require setting up Apache forwarding, Mongrel instances, and more. In this department, Rails really can’t compete with Cake.

More Resources for the Beginner

PHP has perhaps the best online documentation of any language out there. Every function is well documented, and most have user comments below with tips and explanations on various quirks. It’s also a very widely used language, which means a lot more people can help you out if you have issues. Even though CakePHP itself isn’t particularly well documented, it definitely benefits from the many PHP resources out there. Ruby, on the other hand, though things are getting better, isn’t nearly as well documented as PHP and doesn’t really have a central place to go like PHP.net. There also aren’t nearly as many people that are familiar with the language.

CakePHP is Beginner-Friendly

Though CakePHP is lacking in a many areas where Rails really excels, I think it definitely has its place in the world of web frameworks. I would definitely consider using it on smaller-scale projects where I don’t want to deal with the complicated setup of a Rails production environment. It’s also a little more accessible for beginners than Rails because of the vast PHP community. However, for a user requiring a more powerful framework, I currently don’t think there’s much out there that’s better than Rails.

9 Comments

Leave a Reply