Getting a new Oven, Migrating from CakePHP 1.1 to 1.2

So 1.2 is nearly complete, the code is frozen and there are only a few bugs left to squash before the final release is ready. So you want to upgrade your application from 1.1 to 1.2. Although the 1.2 moniker suggests a ‘minor’ version, a lot has changed under the hood and entire API’s have been rebuilt. I’m going to try and focus on the important changes that will affect your applications, and as such won’t be covering all the new features in 1.2.

Loading classes

Loading classes has been entirely rebuilt from the ground up in 1.2. loadHelper(), loadController(), loadComponent(), loadModel(), loadPluginModels(), loadView(), vendor() are all gone. They have all been replaced with the newer App::import() . App::import() is the recommended way of loading all core and app classes. Its use is very simple outside of loading vendor files. Even for many vendor libs it is a straightforward method call.

Show Plain Text
  1. App::import('Model', 'Post');
  2.  

The above would load your Post Model. App::import() is quite flexible and you should refer to the manual for how to load the specific class you want.

Model find() and findAll()

In 1.1 there were a number of different findXX() methods. find(), findAll(), findCount(), findAllThreaded and generateList() were the most commonly used find() methods for me. All of these methods have been replaced by find(). Find now works quite a bit differently. In the past find() methods took a dizzying number of arguments which made them a pain to use. In 1.2 however, we’ve tried to simplify this and your find() calls start looking like the following.

Show Plain Text
  1. // 1.1 findAll()
  2. $this->findAll($conditions, $fields, $order, $limit, $page, $recursive);
  3.  
  4. // 1.2 find('all')
  5. $this->find('all', compact('conditions', 'fields', 'order', 'limit', 'page', 'recursive'));

And while these function signatures seems similar, the newer syntax really starts to shine when you want to define some of the keys.

Show Plain Text
  1. // What used to be
  2. $this->findAll($conditions, null, $order, null, null, $recursive);
  3.  
  4. //Becomes
  5. $this->find('all', compact('conditions', 'order', 'recursive'));

Of course the above examples assume you have the necessary variables declared. As you can see the first argument of find indicates the type of find that you are performing. The core supported find methods are

  • first
  • all
  • count
  • list
  • neighbors
  • threaded

These types can be extended easily as well in your models. A further benefit of using the newer syntax is if you are implementing behaviors that work on find() such as Containable you can pass in those keys as well.

Show Plain Text
  1. $this->find('all', compact('conditions', 'contain'));

This gives you a great deal of flexibility and power with your finds.

Greatly improved form generation

Forms are easier than ever to create. In 1.1 the generateXX() methods worked well, but they seem highly inefficient when compared to the new form creation syntax. Compare the following.

Show Plain Text
  1. //sample form in 1.1.
  2.  
  3. <?php echo $html->formTag('/posts/add'); ?>
  4. <fieldset>
  5.     <legend>Create a new Post</legend>
  6. <?php echo $form->generateInputDiv('Post/title', 'Title', true, 'title is required'); ?>
  7. <?php echo $form->generateInputDiv('Post/body', 'Body', true, 'body is required'); ?>
  8. <?php echo $form->generateSubmitDiv('Submit'); ?>
  9. </fieldset>
  10. </form>
  11.  
  12. //same form in 1.2
  13. <?php echo $form->create('Post'); ?>
  14. <?php echo $form->input('title'); ?>
  15. <?php echo $form->input('body'); ?>
  16. <?php echo $form->end('Submit'); ?>

Both of these generate the same form at the end of the day, however one is far less typing. In addition the 1.2 form offers features the 1.1 does not. These features include automatic passing of error messages from models to view, secured forms, and additional CSS / Javascript hooks. Find our more about the features of the new FormHelper in the book

Another thing to keep in mind when migrating is that a lot of form widget generation used to be in HtmlHelper. All of these methods have been moved to FormHelper.

Validation

Model validation is another area that 1.2 takes leaps and bounds past the capabilities of 1.1. In 1.1 you could only specify a single rule per field and it was required to be a regular expression. In 1.2 you can create multiple rules per field, each with their own error message. In addition to regular expressions validation rules can also be model or behavior callbacks, which take additional parameters. A sample of the new syntax looks like:

Show Plain Text
  1. var $validate = array(
  2.     'title' => array(
  3.         'length' => array(
  4.             'rule' => array('minLength', 10),
  5.             'message' => 'Title must be at least 10 characters long'
  6.         ),
  7.         'no-numbers' => array(
  8.             'rule' => '/^[a-z _-]+$/i'
  9.             'message' => 'Only letters spaces and _ - are allowed',
  10.         )
  11.     ),
  12.     'value' => array(
  13.         'required' => array(
  14.             'rule' => 'notEmpty',
  15.             'message' => 'Value is a required field',
  16.         ),
  17.         'length' => array(
  18.             'rule' => 'numeric',
  19.             'message' => 'Title must be at least 10 characters long'
  20.         ),
  21.     ),
  22. );

You can find out more about all the new validation methods at the cookbook. It should be noted that using this syntax is not required and the old syntax will still work. You just won’t reap the benefits of error messages and multiple validation rules.

renderElement

View::renderElement() has been merged with View::element(). They were always alias’ for each other, however in the future renderElement may be dropped. Furthermore, using element() allows you to leverage element caching, which is new in 1.2.

New View file extension

View files now have a different native extension. .ctp is the new extension supported by default. This can be changed by setting $this->extension = '.thtml' if you want to keep the old .thtml file extension.

Routing

Routing is greatly improved in 1.2 and supports a much wider array of options and parameters than before. How routes are connected is quite a bit different though. In the past

Show Plain Text
  1. $Route->connect('/', array('controller' => 'users', 'action' => 'login'));

Would be the syntax for connecting a route. In 1.2 Router::connect() is called statically to add routes. So your routes have to look like this

Show Plain Text
  1. Router::connect('/', array('controller' => 'users', 'action' => 'login'));

Admin and plugin routing has changed as well. Plugin routes used to be tedious at best, now the plugin key is specified just as you would any other routing key. The same is true for admin/prefixed routes. In the past you would link to admin routes with /admin/posts/index. In 1.2 you can use array('controller' => 'posts', 'action' => 'index', 'admin' => true).

You can read more about the routing enhancements in the cookbook

Overall there have been a ton of changes between CakePHP 1.1 and 1.2, I’ve tried to cover all the ones that I run into daily when switching between 1.1 and 1.2 apps. If there are other common pitfalls let me know and I can add them here. Or you can add them into the cookbook for all to enjoy.

Comments

Even though i switched a while back I got something out of this post. Thanks!

anonymous user on 11/10/08

Good review of some of the basic changes.

anonymous user on 11/10/08

I’d been wondering what happened to those 1.1 VALID_NOT_EMPTY validation techniques! I’d been using the minLength instead, but notEmpty will do the job nicely :) thanks Mark.

anonymous user on 11/10/08

Your multi rule validation example, you wouldn’t need the notEmpty rule, as null is surely shorter than 10 characters? Nit picking I know ;)

Good article, as there are quite a few people in the official irc channel who would benefit from this.

anonymous user on 23/10/08

Neon: You are very correct, I’ve switched it with something that makes more sense in the given context. :)

mark story on 24/10/08

Hi All,
Please help me. I have upgraded 1.1 to 1.2 and cakephp sessions are not working.

Thanks in advance.

Sathish on 4/8/10

Sathish: I don’t know if somebody is reading this but My app/core.php miss a lot of configs so I needed to copy it from original. In this case this line:
Configure::write(‘Session.start’, true);
was needed.

anonymous user on 26/2/14

Have your say:

*
* You can use Textile markup, but be reasonable