Under the hood of CakePHP 2.0

Thanks to excellent Mr. jrbasso for putting together this list for me.
In case one wonders, yes he does know a few things about cake ;)

So, without further ado here’s a couple of things to enjoy in CakePHP 2.0…

__() now works like sprintf()

There were a few complaints about this in the past, as well as the fact that __() used to echo by default.

Now the problem is fixed and the default usage is as follows:

echo __("some %s var", $myVar);

Improved file structure and lazy loading of files

The naming convention is much better and simpler now. No more messing about with underscore’s, etc.
Whatever you have for your class name is what you have for your file name (+”.php”).
Misspelling of model file names ESPeciaALLY (e_s_pecia_a_l_l_y.php) in extreme cases was a common mistake for cake not being able to find the model.
Therefore none of the model specific rules for validation, methods and other logic could be executed.
(The simple debugging and good ol’ copy/paste should be much easier now).

New CakeRequest and CakeResponse

First, CakeRequest gathers all information about the request (in a way like $this->params does, but with a lot more juice).
For example, some responsibilities of the RequestHandler component have been shifted to CakeRequest.
Mark Story has an excellent write-up about this if you wish to learn about
the details.

The counterpart, of sorts, to CakeRequest is CakeResponse… which, as you’ve guessed, works to handle responding to requests.
It consolidates the work, which was previously spread across various components of the system.
Again, I will refer you to Mark Story’s blog to get detailed description about CakeResponse.

The whole idea is to decouple and better organize related tasks from various places in the framework. Good organization helps with maintainability of the framework code, and, in turn, your own.

CakeEmail is a Library now

This change should stop 99% of the questions about how to send email from the model.
Yaayy! You don’t have to break MVC anymore (in your User model):

App::uses('CakeEmail', 'Network/Email');
class User extends AppModel {
  public function afterSave($created) {
    if ($created) {
      $email = new CakeEmail();
      $email->from('me@example.com')->to('new.user@example.com')->subject('Welcome')->send('Hello! This is my message to the new user.');
    }
  }
}

You don’t have to chain the methods as above…

HTML5 methods in Form/Html helper

Even though HTML5 is still a bit infant more and more web applications are beginning to apply its elements. This is especially true in the mobile market.
CakePHP 2.0 has a clever way for the HTML5 implementation, by using the magic __call() method,
to create simple inputs.

Let’s look at the test case to better understand this:

/**
 * test that some html5 inputs + FormHelper::__call() work
 *
 * @return void
 */

  function testHtml5Inputs() {
    $result = $this->Form->email('User.email');
    $expected = array(
      'input' => array('type' => 'email', 'name' => 'data[User][email]', 'id' => 'UserEmail')
    );
    $this->assertTags($result, $expected);

    $result = $this->Form->search('User.query');
    $expected = array(
      'input' => array('type' => 'search', 'name' => 'data[User][query]', 'id' => 'UserQuery')
    );
    $this->assertTags($result, $expected);

    $result = $this->Form->search('User.query', array('value' => 'test'));
    $expected = array(
      'input' => array('type' => 'search', 'name' => 'data[User][query]', 'id' => 'UserQuery', 'value' => 'test')
    );
    $this->assertTags($result, $expected);
  }

PDO and database access performance

In 2.0 CakePHP is switching to the PDO. PDO drivers are stable, native and well-supported. They obviously provide faster and better data access.

Auth is more flexible and supports different authentication methods like “Digest”

Authentication and Authorization are now properly decoupled from one another.
In both cases an app developer has the ability to extend BaseAuthenticate or BaseAuthorize to add new authentication and authorization methods.
CakePHP 2.0 comes with a few core methods (at least at the time of writing this):

  • ActionsAuthorize — Provides the ability to authorize using the AclComponent
  • BasicAuthenticate — Provides Basic HTTP authentication support for AuthComponent
  • ControllerAuthorize — Provides the ability to authorize using a controller callback
  • CrudAuthorize — best explanation is taken from the code doc:

    For example, taking `/posts/index` as the current request. The default mapping for `index`, is a `read` permission check. The Acl check would then be for the `posts` controller with the `read` permission. This allows you to create permission systems that focus more on what is being done to resources, rather than the specific actions being visited.

  • DigestAuthenticate — Provides Digest HTTP authentication support
  • FormAuthenticate — Authenticates the identity contained in a request (i.e. the good ol’ login form)

So much cleaner :)

No more PHP4

Nuff’ said. This makes Cake 2.0 much faster (oh let’s say twice as fast), and no I don’t have evidence to support this claim, by removing a lot of uncessary code to support PHP 4 and 5, not to mention additional logic which would lead on one path or another depending what version of PHP you have installed.
To be more specific, CakePHP 2.0 will support PHP 5.2+ (so it may not be utilizing some of the newer features of PHP 5.3).

Using collections to load Helpers, Behaviors, Components

From CakePHP lighthouse page:

Helpers, behaviors, components, and tasks were restructured for 2.0. After examining the various things these objects did, there were some striking similarities. All the object types except Tasks provided callbacks and custom methods. However, the loading and usage of callbacks was slightly different in each case. For 2.0 these different loading/callback triggering API’s were simplified and made uniform. Using BehaviorCollection as the base of how things should work. Each object type now has a Collection object. This collection object is responsible for loading, unloading and triggering callbacks.

After examining the responsibilities of each class involved in the View layer, it became clear that View was handling much more than a single task. The responsibility of creating helpers, is not central to what View does, and was moved into HelperCollection. HelperCollection is responsible for loading and constructing helpers, as well as triggering callbacks on helpers. By default View creates a HelperCollection in its constructor, and uses it for subsequent operations. The HelperCollection for a view can be found at $this->Helpers.

Components were refactored in 2.0 to solve a number of inconsistencies and provide a more uniform API. In the past Component was the loader and manager of Components for a Controller. In 2.0 ComponentCollection takes over that responsibility and Component is now a base class for components. This unifies the API between Helpers and Components as a collection.
Inside a controller $this->Component has been renamed to $this->Components this makes it more uniform with Behaviors and Helpers.

Custom class names (aliasing) for your Helpers, Behaviors, Components

pulic $helpers = array(
    "Html" => array(
        "className" => "CustomHtml"
    )
);

Plugins are not auto-loaded

You will need to load them in your class or bootstrap.

Models are now lazy loaded

With all this talk about Lazy Loading, this is probably the one that deserves a lot of attention.
Besides, models will not attempt a DB connection until find() (or other DB-actionable) method is called.

p.s. CakePHP 2.0 could be here sooner than people expect. I have a feeling we’ll have RC4 come CakeFest. So, if you have not started thinking about migrating your app to 2.0, now is a good time ;)

  • http://www.dereuromark.de mark

    A really nice summary!

    one thing, though:
    “Besides, models will not attempt a DB connection until find() method is called.”
    I guess you need to say “some DB access method” since updateAll() etc will also have to startup a connection :)

    regarding your PS:
    migration live apps is usually not possible. or a whole lot of work.
    especially if they consist of lets say > 50 models.
    2.0 has so many drastic changes (from class names to file names to other things) that this would need too much time and effort in most cases. those projects will probably stay in 1.3 for a long time.
    new projects, though, can be developed in 2.0, more easily. one problem here is that most of the (own custom) library classes are still in 1.3. those need to be migrated as well. also quite a lot of work. we are talking about helpers, components, behaviors, libs and their test cases…

  • teknoid

    @mark

    Yes, migrating will not be easy… but if you have a live application now is a good time to think about upgrading. Not only to get the benefits of performance, but also your app will grow with the framework, which means maintainability will be improved and further down the road the app won’t be diverging from the core too much, otherwise locking the development to an outdated version.

  • http://grahamweldon.com Graham Weldon

    Upgrading really is not that difficult. Theres a shell to assist the process, and the rest is extremely well documented. By far the best documentation effort we’ve ever seen from the core team.

  • Jose Lorenzo

    @teknoid Very nice summary of the changes on 2.0! As for the performance differences, we have already benchmarked it and it is indeed in some cases twice as fast as 1.3, but in pages involving queries the performance increase is “just” about 40%

    @mark It is actually very easy to migrate the applications, we have budled an upgrade shell to assist you rename files, change the translation functions, use the request objects, etc. I have migrated a bunch on 1.3 plugins already and it just took me about 10 minutes. Good news is that models have not changed in 2.0, so you will only have to focus on the other layers.

  • teknoid

    @Graham Weldon, Jose Lorenzo

    Thanks for your feedback!
    We’ll be migrating a pretty large-scale app to 2.0 in the near future, hopefully my reports of that move will indeed be short and sweet ;)

  • http://www.jotlab.com voidet

    Awesome!

  • Reuben

    Seeing this has made me consider upgrading an app from 1.2 to 1.3.

    We’re about to do some more work on it. Jumping from 1.2 to 2.0 might be too much of a heart attack, and the timing of the release of 2.0 might not be quite right.

  • teknoid

    @Reuben

    As they say, it really depends… if you app is not too complex 1.2 to 2.0 should be possible as well.

  • http://www.bravanews.com AndreSantiago

    I have been developing in CakePHP 1.3 for a few months now. I have a project for a new website that will launch 01/01/2012. I am now 30% finished. Do you think I would be better off stopping development in 1.3 and switching off to 2.0 before going any further?

  • teknoid

    @AndreSantiago

    Yes, there will be no significant API changes at this point.
    I would use 2.0 for any new projects or anything that is relatively “young” at this point.

  • Pingback: CakePHP : signets remarquables du 10/08/2011 au 23/08/2011 | Cherry on the...

  • Harris

    I started experimenting in a new site with cakePHP 2.0. I am trying to implement tests with phpUnit. I have never used tests in either simple php applications or in cakePHP 1.2 1.3.
    Is there a help or tutorial?

  • teknoid

    @Harris

    Mark Story has a post about that (or two). CakePHP manual also covers some aspects.
    But the best way to learn about TDD is to read some general articles online and then get more specific within CakePHP environment, there isn’t much difference between the way testing is done in 1.3 vs 2.0

    … and another great way to learn is just to look at existing test cases for the framework (learn about testing and cake ;)

  • Pingback: Co nowego w cake 2.0? | webbricks

  • Pingback: CakePHP 2.0.0-RC1 Hot and fresh - Ralf Hohoff

  • http://localhost prakash1708

    i had an application in cakephp 1.3
    the app_controller (in webroot) contained a function called ‘initsession’.
    i was able to call this function from other controllers using the syntax $this->initsession.
    but when i migrated to cakephp 2.0, this is giving an error, as under

    Fatal error: Call to undefined method UsersController::initSession() in F:\wamp\www\fraud\app\Controller\users_controller.php on line 160

    please guide me as to what the error could be . regards

  • Pingback: Moving an app from CakePHP 1.3 to CakePHP 2.0… quite painless | brainstorm.net.au