Migrating from CakePHP 1.1 to 1.2
There are several articles out there that talk about migrating from CakePHP 1.1 to 1.2. Many of them have been helpful, but they all seem to be short on information. My migration was anything but simple. So I’m writing this to try and provide as much information as I can about migrating from 1.1 to 1.2. It’s probably impossible to get everything, but I’m hoping my experience in migrating will help someone else out too.
The first place to check out if you planning on upgrading to 1.2 is the CakePHP site. They have a good article on migrating. That’s the perfect place to start. Follow all those steps and test out your application, because it’s possible that’s all you’ll need to do. However, if you have a more complex application, like myself, you’ll probably notice a whole lot more problems.
Deprecated Stuff
The next useful place I would point you is to this information on deprecated stuff. There is a lot of stuff that’s been removed or replaced in 1.2, so if you are using any of this stuff, you’ll have to find a replacement or make changes. One particular problem I ran into was with the use of tagValue(), which has been removed. I was using this method in a lot of places. It’s replacement is:
$form->value()
The ACL Changes
The ACL has changed considerably. This was one of the bigger hurdles I had to face. In my opinion 1.1 had an easy way of programmatically working with the ACL. It required as little code as this:
$aro = new Aro(); $aro->create($this->Department->id, 'Employees', 'Department.' . $this->Department->id);
I found out real quick that it was no longer this simple to create a new ARO. If you are having to go through this transition, it might be helpful to know a couple of things. First, the ACL works a lot like a normal Model now. To create an ARO in 1.2 I had to change my code to something like this:
$department_array['foreign_key'] = $department['Department']['id']; $department_array['parent_id'] = 1; $department_array['model'] = 'Department'; $department_array['alias'] = 'Department.' . $department['Department']['id']; $aro->create(); $aro->save($department_array);
I wasn’t to found of all the extra code that I had to create just to create a new ARO. Not that this is a bad technique, but dealing with the array just makes the process more difficult. That wasn’t my real problem though. My real problem was with setting the parent. I used to call the parent by the alias. I can’t do that anymore. Now I have to pass the actual ID as the parent. This presented another problem. How am I going to get that ID if I don’t know what it is? There is a new method that can be used and you can read about it here. However, I didn’t like that idea because it wouldn’t update the information if I changed it. So I reverted to my own solution. This is more complex, but in the long run it will save me time and I won’t have to write a lot of code to replace what I already have in place from 1.1.
In my opinion the application should be smart enough to know what to do if I want to pass a parameter as Model.id. And for some things I don’t have a Model.id format. I have a group called “Employees”. So I wanted my application to be smart enough to know what to do if I pass “Employees” as a parent. After a little brainstorming I found what I thought would be the easiest way to create ARO’s and ACO’s.
$this->aclMagic('createAro', 'Department.' . $this->Department->id, 'Employees');
Pretty simple, right? I set out to make it this simple to create ARO’s and ACO’s. Here is the method that I came up with.
function aclMagic($action, $alias = null, $parent = null) { if ($action) { if (strpos($alias, ".") !== false) { $temp_array = explode(".", $alias); $model = $temp_array[0]; $foreign_key = $temp_array[1]; } else { $model = null; $foreign_key = null; } if ((strpos($parent, "/") !== false) && (strpos($action, "Aco") !== false)) { $temp_array = explode("/", $parent); $parentNode = $temp_array[0]; $parent_array = $this->User->findAco("alias = '" .$parentNode. "'"); $parent_array = $this->User->findAco("alias = '" .$temp_array[1]. "' and parent_id = " .$parent_array[0]['Aco']['id']); $parent_id = $parent_array[0]['Aco']['id']; } else { $parentNode = $parent; if ((strpos($parentNode, ".") !== false) && (strpos($action, "Aro") !== false)) { $temp_array = explode(".", $parentNode); $parent_array = $this->User->findAro("model = '" .$temp_array[0]. "' and foreign_key = " .$temp_array[1]); $parent_id = $parent_array[0]['Aro']['id']; } elseif ((strpos($parentNode, ".") !== false) && (strpos($action, "Aco") !== false)) { $temp_array = explode(".", $parentNode); $parent_array = $this->User->findAco("model = '" .$temp_array[0]. "' and foreign_key = " .$temp_array[1]); $parent_id = $parent_array[0]['Aco']['id']; } elseif ($parentNode != null && !is_int($parentNode) && strpos($action, "Aro") !== false) { $parent_array = $this->User->findAro("alias = '" .$parentNode. "'"); $parent_id = $parent_array[0]['Aro']['id']; } elseif ($parentNode != null && !is_int($parentNode) && strpos($action, "Aco") !== false) { $parent_array = $this->User->findAco("alias = '" .$parentNode. "'"); $parent_id = $parent_array[0]['Aco']['id']; } } $aclData = array('model' => $model, 'foreign_key' => $foreign_key, 'parent_id' => $parent_id, 'alias' => $alias); switch ($action) { case "createAro": $aro = new Aro(); $aro->create(); $aro->save($aclData); break; case "createAco": $aco = new Aco(); $aco->create(); $aco->save($aclData); break; case "setParentAro": $aro = new Aro(); $aroData = $this->User->findAro("model = '" .$model. "' and foreign_key = " .$foreign_key. " and alias = '" .$alias. "'"); $aro->id = $aroData[0]['Aro']['id']; $aro->save($aclData); break; case "setParentAco": $aco = new Aco(); $acoData = $this->User->findAco("model = '" .$model. "' and foreign_key = " .$foreign_key. " and alias = '" .$alias. "'"); $aco->id = $acoData[0]['Aco']['id']; $aco->save($aclData); break; case "deleteAro": $aro = new Aro(); $aroData = $this->User->findAro("model = '" .$model. "' and foreign_key = " .$foreign_key. " and alias = '" .$alias. "'"); $aro->id = $aroData[0]['Aro']['id']; $aro->delete(); break; case "deleteAco": $aco = new Aco(); $acoData = $this->User->findAco("model = '" .$model. "' and foreign_key = " .$foreign_key. " and alias = '" .$alias. "'"); $aco->id = $acoData[0]['Aco']['id']; $aco->delete(); break; default: //Do Nothing break; } } //if ($action) }
There are a couple of things to note here. I put this method in my AppController. My User Model is available to my entire application with $uses = array(’User’). I have a couple of methods in my user model that query my ACL tables in my database. These queries is what grabs the id of a particular record.
function findAco($condition) { $sql = "select * from acos AS Aco where " . $condition; $result = $this->query($sql); return $result; } function findAro($condition) { $sql = "select * from aros AS Aro where " . $condition; $result = $this->query($sql); return $result; }
This code may still be a little buggy, but it works for the most part. There may be an easier way to do this too, but for me this solved the changes made to the ACL and still allowed me to create ARO’s and ACO’s easily without having to create arrays of data every time.
Multiple Select Lists
This is one request I’ve seen all over the place. In most cases I don’t want a select list, but rather a list of checkboxes. So in 1.1 I used a checkbox helper from the bakery. 1.2 has the capability to use checkbox lists built in. Here’s how you do it.
In your controller:
$categories = $this->Post->Category->find('list'); $this->set(compact('categories'));
In your view this seems to work (not sure if it’s the recommended way though):
< ?php echo $form->select('Category.Category', $categories, null, array('multiple' => 'checkbox'));?>
The other problem I had with multiple select lists is that the new find(’list’) wouldn’t get data that was modified in an afterFind method that I had. In 1.1 this seemed to work, so for 1.2 I solved this issue by writing my own method. In my user database I have first_name and last_name fields. I want these two fields combined to show up as the option in my select list. From what I can tell, find(’list’) can’t do it. So I wrote my own little method to take care of the problem. The afterFind method is some code that was published by someone else from the bakery.
function afterFind($results) { foreach ($results as $key => $val) { if (isset($val['User']['nick_name']) && isset($val['User']['last_name'])) { $results[$key]['User']['fullname'] = $val['User']['nick_name'] . ' ' . $val['User']['last_name']; } } return $results; } function generateListByName() { $results = $this->find('all', array('recursive' => 0, 'fields' => array('User.id', 'User.nick_name', 'User.last_name'), 'order' => 'last_name, nick_name')); $results = Set::combine($results, '{n}.User.id', '{n}.User.fullname'); return $results; }
To use it just drop the method into your User Model and call it using this line:
$this->Department->User->generateListByName();
Worked like a charm for me. This is an issue that I’ve seen questions about on the web with no good answer. So I hope this helps someone out.
A Model Change
The only other model problem I ran into was with the execute method. I think it’s been removed. I didn’t see anything in the API about it and it gave me a problem with one of my queries. I just changed it to the $this->query method and it worked.
I’m sure there are many more migration problems that people will run into that I didn’t mention here. But these are some of the main problems that I noticed in my migration process. Hope this helps someone out. Feel free to comment on your issues that you had with the migration process and post any solutions that you came up with.


