There will be a number of backwards compatibility (BC) breaks in the CakePHP 3.0.0 release. I thought it might be helpful to go over some of the reasons breaks in compatibility have been made. Each time we’ve had to break compatibility with 2.x we’ve done so because the existing behaviour fell into a few categories of problems. I’ll go over a few of the bigger categories in detail.
PHP has changed
In the years since CakePHP 2.0.0 was released, PHP has dramatically changed. The features in PHP5.3+, and composer have radically changed how developers work in PHP. To be frank, CakePHP has fallen a bit behind. While we were really good about backwards compatibility, we might have been a bit slow to make breaking changes and adopt new tools of our trade. For CakePHP 3.0, we’ve decided to move the version requirements up to PHP5.4, and fully embrace composer. By adding namespaces, all the class names in CakePHP have changed. Changing all the class names represents a significant break in compatibility. We’ve tried to reduce the tedium of this change by providing an upgrade tool to help with some of the more tedious naming changes.
Adopting composer has meant that the app skeleton and framework have become separate repositories. With the huge selection of great packages available throught composer, CakePHP has started to pull in a few dependencies. There are only a handful of dependencies and they are all compact libraries that provide functionality that wouldn’t help make CakePHP better if we wrote it ourselves. For example
password_compat allow us to have much better datetime and password hashing functionality without having to spend time building it ourselves. Plugins in CakePHP 3.0, will also be installable through composer, and the old vendor directories should be replaced entirely via composer.
Ideas that didn’t work out so well
Another class of things that have been ‘broken’ in CakePHP 3.0 are what I refer to as the ‘good idea at the time’ features. A few specific examples of this are:
- Named parameters – I’m not personally convinced these were ever a good idea. They were non-standard, provided no measurable value, and were a pain to integrate with others tools.
- Full page caching – The 1.x era full page caching worked at the time, but has aged poorly. It has a number of limitations now that are not addressable without breaking the behaviour. If we were going to replace the feature I would want to use Edge Side Includes which is a W3C draft. ESI is the same specification that standalone response caching tools like Varnish use. However, upon reflection it didn’t make sense to build a poor-man’s varnish. Generally applications dealing with the volumes of traffic that justify varnish, can afford the additional investment required to deploy varnish.
One area where we’ve intentionally not broken compatibility since the 1.2 days is the model layer. Because models and your application’s data are so fundamental to how you work, we’ve intentionally not changed the model layr for many years. While some people really like the models in CakePHP, many do not. I personally feel that object mappers like SQLAlchemy and DataMapper are more elegant solutions that make it easier to work with relational databases. For CakePHP 3.0, the ORM has been entirely replaced with a datamapper inspired approach. Jose Lorenzo has put a monumental amount of work into the ORM and I think it is pretty fantastic. Being able to do things like:
- // Use multiple custom finder methods.
- // Conditions and contain associations.
- $query = $this->Articles->find()
- ->where(['Articles.user_id' => 2])
- ->contain(['Comments', 'Tags']);
Is pretty fantastic in my books. Association eager loading has been made a key part of the ORM, and annoying features like
recursive have been removed. There are also new easier to use features for connecting associations and creating validators. Of all the changes in CakePHP, I think the ORM is the most exciting. I suggest you checkout the ORM documentation for more details.
In more than a few places compatibility was broken to create better cohesion across CakePHP. I can’t count the times that I’ve had to look up how specific classes need to be configured. For 3.0, AD7six has done a great job in unifying all the important parts of the framework. If you want to read or write configuration you can:
- // Read all configuration
- // Read a single config value.
- // Set multiple config values
- $obj->config(['key' => 'value', 'key2' => 'value']);
- // Set a single value.
- $obj->config('key', 'value');
All classes that have settings can be interacted with via the same methods. CakePHP provides these configuration features as a trait making it a snap to have consistent methods in your plugins/application.
The callbacks in the models, components, and helpers has maintained compatibility with 2.0.0, throughout all of 2.x. However, in 2.2 CakePHP got a full fledged events subsystem. The new events subsystem had a number of advantages over the old callbacks, and for 3.0, we wanted to choose one solution. We have removed the old style callbacks, and now all framework callbacks are provided through events.
While CakePHP 3.0 does contain a number of backwards incompatible changes, I think they were all justified changes that will help make CakePHP faster, and simpler to use in the future. Migrating existing applications will not be easy, but I think the changes will be worth it in the end.