Alternative Methods for Working with hasAndBelongsToMany Associations
2 : Tutorial
As of 1.1.12.4205, CakePHP's current functionality for working with HABTM associations works very well for most applications, particularly those that lend themselves well to using multiple-selectTags or checkboxes. This article looks at proposed methods for adding or removing join records between two models that don't rely on bulky arrays and that minimize the amount of SQL executed on the database.
Using the code described on the previous page is quite simple. Once you've got it loaded into your app_model, you can do something like the following.
Let's say you have:
User hasAndBelongsToMany UserType
A really simple model function from within your users_controller.php would look something like this:
Your view could then have code that looked like this:
This example uses links, but you could really do whatever, including continuing to use multiple selects. An example might be a selectTag, an Add button, and a table. The table would be populated with UserTypes already assigned to the User, and the selectTag would contain those that have not. When the user selects one or more elements from the multi-select and hits add, the controller gets back somewhere within $this->data an array of ids for the associated model. Just stick that array of ids into the $assoc_ids parameter of addAssoc and deleteAssoc and it'll add each one to the joins for that model without rebuilding the whole group.
Enjoy!
Let's say you have:
User hasAndBelongsToMany UserType
A really simple model function from within your users_controller.php would look something like this:
Controller Class:
<?php
function assign_user_type($user_id, $user_type_id) {
$this->User->id = $user_id;
//alternatively, you can skip the line above and make the following line
//$this->User->addAssoc('UserType',$user_type_id,$user_id);
$this->User->addAssoc('UserType',$user_type_id);
$this->setFlash('User has been assigned.');
$this->redirect('/users/assignments');
}
function unassign_user_type($user_id, $user_type_id) {
$this->User->id = $user_id;
//alternatively, you can skip the line above and make the following line
//$this->User->deleteAssoc('UserType',$user_type_id,$user_id);
$this->User->deleteAssoc('UserType',$user_type_id);
$this->setFlash('User has been unassigned.');
$this->redirect('/users/assignments');
}
?>
Your view could then have code that looked like this:
View Template:
<!-- we're going to assume you've already defined in your view somewhere the function is_assigned() -->
<?php foreach($user_types as $user_type): ?>
<BR><?php echo $user_type['UserType']['name']; ?>
<?php if(is_assigned($user,$user_type): ?>
<?php echo $html->link('Unassign',"/users/unassign_user_type/{$user['User']['id']}/{$user_type['UserType']['id']}");
<?php else: ?>
<?php echo $html->link('Assign',"/users/unassign_user_type/{$user['User']['id']}/{$user_type['UserType']['id']}");
<?php endif; ?>
<?php endforeach;?>
This example uses links, but you could really do whatever, including continuing to use multiple selects. An example might be a selectTag, an Add button, and a table. The table would be populated with UserTypes already assigned to the User, and the selectTag would contain those that have not. When the user selects one or more elements from the multi-select and hits add, the controller gets back somewhere within $this->data an array of ids for the associated model. Just stick that array of ids into the $assoc_ids parameter of addAssoc and deleteAssoc and it'll add each one to the joins for that model without rebuilding the whole group.
Enjoy!
Comments
Comment
1 Works great
Thanks :-)
Comment
2 a
Could you please post an example, I don't get it at all.
Thanks
Comment
3 Holy simplification batman