分类:
2007-09-14 16:11:36
保存hasOne, belongsTo, 以及hasMany的关联model是非常简单的:你仅需要将外键设置为关联model的ID。一旦完成,你也仅需要调用model的save()方法,这样所有的东东都会正确的关联了。
但是对于hasAndBelongsToMany,就有点晦涩了,但是我们已经特意让它尽可能简单。继续我们的例子,我们需要一些表单,这些表单将Tag关联到Post。现在让我们创建一个表单,此表单创建post,以及将他们和一个存在的tag列表关联。
事实上,你可能喜欢创建一个表单来创建新的tag,并将他们在空中关联-但是出于简单,我们仅需要为你说明如何将他们关联,并让你得到它。
在Cake中,当你正保存它自己的model,tag名(如果你在使用HTML helper)应该是'Model/field_name'.让我们从创建post的表单部分开始吧:
创建post的/app/views/posts/add.thtml 表单
<h1>Write a New Posth1> <table> <tr> <td>Title:td> <td>php echo html->input('Post/title')?>td> tr> <tr> <td>Body:<td> <td>php echo $html->textarea('Post/title')?>td> tr> <tr> <td colspan="2"> php echo $html->hidden('Post/user_id', array('value'=>$this->controller->Session->read('User.id')))?> php echo $html->hidden('Post/status' , array('value'=>'0'))?> php echo $html->submit('Save Post')?> td> tr> table> |
当前用的表单仅创建Post记录。让我们增加一些代码使你将给定的Post绑定到一个或多个Tag:
/app/views/posts/add.thtml (增加的Tag 关联代码)
<h1>Write a New Posth1> <table> <tr> <td>Title:td> <td>php echo $html->input('Post/title')?>td> tr> <tr> <td>Body:td> <td>php echo $html->textarea('Post/title')?>td> tr> <tr> <td>Related Tags:td> <td>php echo $html->selectTag('Tag/Tag', $tags, null, array('multiple' => 'multiple')) ?> td> tr> <tr> <td colspan="2"> php echo $html->hidden('Post/user_id', array('value'=>$this->controller->Session->read('User.id')))?> php echo $html->hidden('Post/status' , array('value'=>'0'))?> php echo $html->submit('Save Post')?> td> tr> table> |
对于一个调用,为了让controller的$this->Post->save()保存新Post和它关联的Tag之间的联系,字段名必须是"Tag/Tag"形式(已显示的名字属性看起来是'data[ModelName][ModelName][]'),已提交的数据必须为一个ID,或者关联记录的ID数组。因为我们在这里正使用多个选择,所以提交的Tag/Tag数据应该为ID数组。
这里的$tags变量仅是一个数组,里面的键是可能的Tag的ID,值为多选元素里的显示的Tag名。
当创建应用程序时,你偶尔可能希望为一些特别的情况改变model关联信息。如果model文件里的关联设置给你太多(或不够)信息,你可以使用2个model函数为下一次的查找绑定和解除绑定关联。
让我们建立一些model,以至我们可以看看bindModel()和unbindModel()是如何工作的。我们将从2个model开始:
leader.php 和 follower.php
class Leader extends AppModel { var $name = 'Leader'; var $hasMany = array( 'Follower' => array( 'className' => 'Follower', 'order' => 'Follower.rank' ) ); } ?>
class Follower extends AppModel { var $name = 'Follower'; } ?> |
现在,在LeadersController中,我们可以使用Leader Model中的find()方法准备一个Leader以及它的关联Follower。从上面可以看到,Leader model的关联数组定义了一个"Leader hasMany Followers"的关系。出于描述的目的,让我们使用unbindModel()去除那个关联中间controller。
leaders_controller.php (部分)
function someAction() { //This fetches Leaders, and their associated Followers $this->Leader->findAll(); //Let's remove the hasMany... $this->Leader->unbindModel(array('hasMany' => array('Follower'))); //Now a using a find function will return Leaders, with no Followers $this->Leader->findAll(); //NOTE: unbindModel only affects the very next find function. //An additional find call will use the configured association information. //We've already used findAll() after unbindModel(), so this will fetch //Leaders with associated Followers once again... $this->Leader->findAll(); } |
unbindModel()函数对其他关联类似:仅需要改变关联类型名以及model 类名。unbindModel()的基本使用方法如下:
普通的 unbindModel() 实例
$this->Model->unbindModel(array('associationType' => array('associatedModelClassName'))); |
既然我们成功移除了空中的一个关联,还是让我们增加一个吧。还没有Principle的Leader需要一些关联的Principle。我们的Principle model的文件还不太丰富,除了$name变量语句。让我们把这些Principle关联到Leader吧(而且为了跟踪查找函数哟):
leaders_controller.php (部分)
funciton anotherAction() { //There is no Leader hasMany Principles in the leader.php model file, so //a find here, only fetches Leaders. $this->Leader->findAll(); //Let's use bindModel() to add a new association to the Principle model: $this->Leader->bindModel( array('hasMany' => array( 'Principle' => array( 'className' => 'Principle' ) ) ) ); //Now that we're associated correctly, we can use a single find function //to fetch Leaders with their associated principles: $this->Leader->findAll(); } |
bindModel()函数可以便于创建一个新的关联,但是如果你想改变给定关联的排列顺序或则其他参数,它也会有用。
你已经有了它。bindModel的基本使用是封装一个普通的关联数组,在此数组里,它的键会在你试图创建的关联后命名:
普通 bindModel() 实例
$this->Model->bindModel( array('associationName' => array( 'associatedModelClassName' => array( // normal association keys go here... ) ) ) ); |
请注意,你的表需要正确的键(或者正确配置的关联数组)来绑定model。