I've used CakePHP for a lot of projects now. There's no comparison to Ruby on Rails. Rails is smartly integrated,
well-designed, and sits on top of an elegant language. CakePHP is an admitted ripoff of
Rails that sits on a popular but terrible language. It copies Rails - almost randomly - without copying
any of the stuff that makes Rails great. And PHP is a language plagued by indecision, delays, and paradigms from the
What makes Rails great?
- An ActiveRecord implementation that isn't brain-dead. The Object Relational Model is, you know, actually
- Lazy-loading of records that allows as-needed fetching of model associations instead of a dumb and
unintuitive $recursive variable.
- Actual documentation that doesn't suck (not that it didn't suck in the early years). Cake's
has been getting better lately, but it's still got a long way to go.
- Massive community of great libraries and plugins.
What makes CakePHP awful?
- Arbitrary and seemingly random nesting of HTTP input parameters. It gets to the point where I sometimes access
$_GET and $_POST directly, and just carefully sanitize the data myself.
- Default routing does not use REST, and is difficult (but not impossible) to coerce into anything resembling
- Model instances are represented as PHP arrays instead of objects. So it's like a struct, except uglier,
and you can basically set a few class variables on the model, then call a class method, which simulates an object
method. Nice. The CakePHP core team's position is: this is a deliberate design decision so users cannot call
instance methods in the view. So not only is the decision based on stupid reasoning, it's not even a
- Ridiculous schema manager that has noble intentions, but tries to be too clever. Instead of making you write
your own schema changes like Rails does, it tries to infer the changes after the fact (by diffing the actual schema) - with
disastrous results. Let's say you rename a column and want to use the cake console to capture that change in the schema manager.
Now let's look at the generated schema change that was automatically inferred. Instead of renaming, it will drop the
column and make a new one, which means - yes - all your old column
data is now gone. This is because there's no way to tell with certainty the difference between a rename and
a drop/add after it has already happened. But it matters. What they're trying to do can't be done. Instead they try
to do it anyway and make users deal with the data loss.
Cake doesn't even try to hide the fact that its cloning Rails
in PHP, but it's at a disadvantage from the start because PHP's syntax is just so much worse. And they
use arrays to represent objects. And PHP's array syntax is terrible. Unbelievably terrible. Which makes the decision
to go all-in on PHP arrays baffling. I spend the majority of my
time in Cake trying to manipulate arrays-of-arrays-of-arrays-of-arrays that are supposed
to represent some kind of shoddy struct, then mangling with model associations that require about 5 nested arrays to
define. Add to this the fact that CakePHP tries to "innovate" its way around some of its shortcomings in
a less-than-brilliant way (like, um, $recursive) and you get a steaming pile of garbage that's only marginally
better than just coding a PHP project from scratch.
Rails's smart design has come at a cost. In the past, they haven't been shy about breaking backwards
compatibility, sometimes in a big way, to cut out cancerous ideas before they take hold. It's a community that
acknowledges mistakes and embraces their eradication. And Ruby is an elegant language with strong design and is
under active development. PHP on the other hand has languished for years, most notably with a critical security bug
called $register_globals. On top of that, they've been slow to introduce object support, type-checking, and
sometimes make terribly confusing decisions (like the decision to call a feature overloading that has
absolutely nothing to do with method overloading in the traditionally accepted sense of the word).
To be fair, here's what I don't like about Rails (and Ruby):
- Massive list of reserved variable names, which of course will throw a cryptic and seemingly unrelated error
if you use them.
- Concise syntax that sometimes resembles perl. Yes, perl.
- Bizarre decision to use "end" to close blocks instead of something sensible, like um, anything else.
More typing for no good reason. The cherry on top that makes this not OK is that while its illegal to define a
variable named "end," its fine to define a function named "end."