Intersecting Entities on CakePHP Models
I’m creating a User Model as shown on the data model to the right. In this model, I’d like to be able to assign several Roles to each User. To do this, I’d need to add an “intersecting” entity (UserRole). However, I couldn’t figure out how to implement an intersecting entity in CakePHP. But after further reading, it turns out that there is a particular type of association in CakePHP specifically for handling intersections and that is the hasAndBelongsToMany (HABTM) association.
It turns out the “UserRole” does not become a class of it’s own, but instead will only be used as a joining table. In effect, we’re still associating User with Role using UserRole as the joining table. Though as Abba pointed out, it’s possible to make UserRole as another class using the “with” parameter.
So to do this, following the CakePHP convention, I created the following tables:
–
– Table structure for table `roles`
–CREATE TABLE `roles` (
`id` int(11) NOT NULL auto_increment,
`name` varchar(50) NOT NULL,
`description` varchar(255) NOT NULL,
`initControllerAction` varchar(50) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=5 ;–
– Dumping data for table `roles`
–INSERT INTO `roles` VALUES (1, ‘Admin’, ‘System Administrator’, ‘test’);
INSERT INTO `roles` VALUES (2, ‘User’, ‘Regular User’, ”);
INSERT INTO `roles` VALUES (3, ‘Visitor’, ‘Visitor’, ‘test’);
INSERT INTO `roles` VALUES (4, ‘Operator’, ‘System Operator’, ‘test’);– ——————————————————–
–
– Table structure for table `users`
–CREATE TABLE `users` (
`id` int(11) NOT NULL auto_increment,
`username` varchar(50) NOT NULL,
`first_name` varchar(50) NOT NULL,
`last_name` varchar(50) NOT NULL,
`password` varchar(32) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=2 ;–
– Dumping data for table `users`
–INSERT INTO `users` VALUES (1, ‘admin’, ‘Test’, ‘Administrator’, ‘cdd80313584fc62e1da825e72be7d27d’);
– ——————————————————–
–
– Table structure for table `users_roles`
–CREATE TABLE `users_roles` (
`user_id` int(11) NOT NULL,
`role_id` int(11) NOT NULL,
PRIMARY KEY (`user_id`,`role_id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1;–
– Dumping data for table `users_roles`
–INSERT INTO `users_roles` VALUES (1, 1);
INSERT INTO `users_roles` VALUES (1, 2);
After creating and populating the tables, we’ll simply need to update the User model (app/models/user.php) to add the following lines:
class User extends AppModel {
var $name = 'User';
// this is how to implement an intersecting entity in CakePHP
var $hasAndBelongsToMany = array(
'Role' => array (
'className' => 'Role',
'joinTable' => 'users_roles',
'foreignKey' => 'user_id',
'associationForeignKey'=> 'role_id',
'conditions' => '',
'order' => '',
'limit' => '',
'unique' => true,
'finderQuery' => '',
'deleteQuery' => ''
)
);
}
I tried doing a simple pr($user) from my authentication program and it worked like magic
.
3 Comments »
Leave a comment
-
Recent
- My Move to the OSX (the dark-side)
- Skype & Apache conflict
- Simple yet effective way to replicate/mirror a database (any database at that)
- MySQL .frm recovery
- cakePHP calls crashing Apache
- Reformatting the default CakePHP layout (default.ctp)
- Syntax highlighting CakePHP using Eclipse
- Intersecting Entities on CakePHP Models
- Integrating Flickr into my PHP web-app
- Installing CakePHP
- Accessing a POP3 mailbox using PHP
-
Links
-
Archives
- October 2009 (2)
- April 2009 (2)
- February 2008 (1)
- January 2008 (6)
-
Categories
-
RSS
Entries RSS
Comments RSS
I am hoping to be able to post a bit of code in your comments.
To generate a Model out of the join table. Use the “with” array key in your relationship.
var $hasAndBelongsToMany = array(
'className' => 'Role',
'foreignKey' => 'user_id',
'associationForeignKey => 'role_id',
'joinTable' => 'roles_users',
'with' => 'UserRole'
);
This will add a model named UserRole automagically. If you have an actual file UserRole in your models folder it will use that. If you don't it will extend AppModel and create a basic model for you.
This is of course the 1.2 branch. ( I believe the stable 1.2 release has this feature, if not the svn surely does )
Hope that makes your CakePHP experience even better.
Thanks for that note Abba, that is certainly appreciated.
I did what you suggest but I have no idea how to show the fields of the ROLE table on controller, neither on the view.
Could you help me please?
Thanks.