问题描述
我有两个模型与一个HABTM(拥有和属于许多)关系:Qsets和问题。
下面的动作(在QsetsController.php) qsets_questions表中的一个新行,新的问题出现在新的qset中。但是会更新现有的行,导致该问题从之前的qset开始,并添加到新的qset。
我在做什么错误?
public function admin_add_question($ qset_id,$ question_id){
//找到qset ...
$ qset = $ this-> Qset-> find('first',array('id'=> $ qset_id));
$ this-> Qset-> QsetsQuestion-> create();
$ data = array(
Qset=> array(id=> $ qset_id),
Question=> array(id=> $ question_id)
);
Controller :: loadModel('Question');
$ r = $ this-> Question-> save($ data);
$ this-> Session-> setFlash('Question id ['。$ question_id。'] added。');
$ this-> redirect($ this-> referer());
}
如果我的描述不清楚, p>
添加问题之前
** Qset 1 **
问题1
问题2
** Qset 2 **
问题3
问题4
在向Qset 2添加问题2时应该发生什么
** Qset 1 **
问题1
问题2
** Qset 2 **
问题3
问题4
问题2
会发生什么...
** Qset 1 **
问题1
< ---- removed
** Qset 2 **
问题3
问题4
问题2
更新:
这是一个转储我的qsets_questions表:
CREATE TABLE`qsets_questions` $ b`id` int(11)NOT NULL AUTO_INCREMENT,
`question_id` int(11)NOT NULL,
`qset_id` int(11)NOT NULL,
PRIMARY KEY `)
)ENGINE = MyISAM DEFAULT CHARSET = latin1 AUTO_INCREMENT = 64;
解决方案:
这里是工作版本,感谢@nuns
public function admin_add_question($ qset_id,$ question_id){
$ this-> Qset-> QsetsQuestion-> create();
$ data = array(
qset_id=> $ qset_id,
question_id=> $ question_id
);
Controller :: loadModel('Question');
$ this-> Question-> QsetsQuestion-> save($ data);
$ this-> Session-> setFlash('Question id ['。$ question_id。'] added。');
$ this-> redirect($ this-> referer());
}
正在发生:
您没有使用超级有用的HABTM关系魔法。而不是把这个表当作一个关系表,蛋糕去定义的模型,看到你定义的关系和primaryKeys和displayFields等。
有一个复杂的HABTM表。但是,如果是这样,你的数据数组已经乱七八糟了,因为你没有分别添加问题
和 Qset
。我的意思是,你不做
$ data = array('question'=> array ;'new_question'),
'Qset'=> array('name'=>'let say qset'));
$ this-> Question-> saveAll($ data);
这样,你让蛋糕解决HABTM关联,并且数据结构可以。但是你在你的模型文件夹中有你自己的QsetsQuestion模型。所以你保存的数据应该像任何其他表一样,像这样
$ data = array('qset_id'=& $ qset_id,
'question_id'=> $ question_id);
$ this-> Question-> QsetsQuestion-> save($ data);
并且在qsets_questions表中创建一个新的id,与新的关系,就像你想要的。
但请注意,由于您使用自己的模型为此,如果您没有正确设置验证,您可能有相同的外键对
经过一番澄清后, ,上面的解决方案解决了问题,但实际上并不是这种行为的原因。
Cakephp有一个帮助我了解HABTM协会(寻找挑战IV)。
我知道我在给出的解决方案帮助你的问题,但它是在你的感觉下你有一个 QsetsQuestion
模型文件。因为你没有,解决方案将是所有问题
关联,并将它们添加为一个新的数组。 或实际上创建了一个 QsetsQuestion
模型,并使这样的关联:
Qset hasMany QsetsQuestion
QsetsQuestion belongsTo Qset,Question
问题有多个Qsets。
或改变蛋糕的行为...没有一个看起来漂亮,我知道。
因此,解决方案的摘要:
-
保存新的Qset-Question关联,检索先前存储的关联,将其保存到要保存的数组中并保存。
//找到以前关联的Qsets,让我们说它是1,2,3和4
$ data = array('question'=> array('id'=> 1),
'Qsets '$> array('Qsets'=> array(1,2,3,4,$ new_qset));
$ this-& code>
注意没有 QsetsQuestion $ c $因为它不存在,这应该是第一个选项,因为HABTM模型不复杂
或
-
在您的模型文件夹中创建
QsetsQuestion
,并如上所述更改关联控制器上的部分将是$ data = array('qset_id'=> 1,'question_id'=> 1 )
$ this-> Question-> QsetsQuestion-> save($ data); // also works with $ this-> Qset-> QsetsQuestion
它更简单(也许),但你必须创建一个新文件,并记住检查没有以前类似的关联(检查是否存在2-2元组插入它之前)。简单的验证规则应该有效。
或
- 更改cakephp行为...我不喜欢这个。
I have two models with a HABTM (Has and belongs to many) relationship: Qsets and Questions.
The following action (in QsetsController.php) should result in a new row in the qsets_questions table, with the new question appearing in the new qset. But instead it updates existing rows, resulting in that question begin taken from a previous qset and added to the new one.
What am I doing wrong?
public function admin_add_question( $qset_id, $question_id) {
//find the qset...
$qset = $this->Qset->find('first', array('id'=>$qset_id));
$this->Qset->QsetsQuestion->create();
$data = array(
"Qset"=> array ("id"=>$qset_id),
"Question"=>array ("id"=>$question_id)
);
Controller::loadModel('Question');
$r= $this->Question->save($data);
$this->Session->setFlash('Question id['.$question_id.'] added.');
$this->redirect( $this->referer() );
}
In case it wasn't clear from my description, here happens:
Before adding a question...
**Qset 1**
Question 1
Question 2
**Qset 2**
Question 3
Question 4
What should happen when adding Question 2 to Qset 2
**Qset 1**
Question 1
Question 2
**Qset 2**
Question 3
Question 4
Question 2
What happens instead...
**Qset 1**
Question 1
<----removed
**Qset 2**
Question 3
Question 4
Question 2
update:Here's a dump of my qsets_questions table:
CREATE TABLE `qsets_questions` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`question_id` int(11) NOT NULL,
`qset_id` int(11) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=64 ;
Solution:
Here's the working version, thanks to @nuns
public function admin_add_question( $qset_id, $question_id) {
$this->Qset->QsetsQuestion->create();
$data = array(
"qset_id"=>$qset_id,
"question_id"=>$question_id
);
Controller::loadModel('Question');
$this->Question->QsetsQuestion->save($data);
$this->Session->setFlash('Question id['.$question_id.'] added.');
$this->redirect( $this->referer() );
}
Ok, here is what I think is happening:
Your not using the super useful HABTM relation magic. Instead of treating this table as a mere relation table, cake goes to the defined model an sees the relations you have defined and primaryKeys and displayFields, etc.
That's ok when you have a complicated HABTM table. But if that's the case, your data array is all messed up, because your not adding a Question
and Qset
separately. What I mean is, your not doing
$data = array('Question'=>array('title'=>'new_question'),
'Qset'=>array('name'=>'lets say qset'));
$this->Question->saveAll($data);
Doing that, you let cake resolve the HABTM association for you, and that data structure would be ok. But you have your own QsetsQuestion model in you model folder. So the data you save should be like with any other table, like so
$data = array('qset_id'=> $qset_id,
'question_id'=> $question_id);
$this->Question->QsetsQuestion->save($data);
And that creates a new id in qsets_questions table, with the new relation, just like you want.
Be careful, though, since your using your own model for this, if you don't set you validations correctly, you might have the same pair of foreign keys a lot of times, because by default cake just check that the id must be unique.
[EDIT]After a bit of clarification, the solution above does solve the "problem", but isn't actually the reason for this behavior.
Cakephp has a feature
By default when saving a HasAndBelongsToMany relationship, Cake will delete all rows on the join table before saving new ones. For example if you have a Club that has 10 Children associated. You then update the Club with 2 children. The Club will only have 2 Children, not 12.
So when you want to add a new row, cake deletes all previous associations and add the new ones. A way to solve this is to find all the Qsets
that belong to a question and add them to the $data
array (with the addition of the new question association you want to add). This link helped me to understand HABTM associations (look for "Challenge IV").
I know the solution I gave before helped you with the "problem", but it was made under the impression you had a QsetsQuestion
model file somewhere. Since you don't, the solution would be to get all Questions
associated and add them as a new array. Or actually create a QsetsQuestion
model, and make the associations like this:
Qset hasMany QsetsQuestion
QsetsQuestion belongsTo Qset, Question
Question hasMany Qsets.
Or change the behavior of cake... None of them seems pretty, I know.
So, summary for solutions:
Every time you want to save a new Qset-Question association, retrieve the previously stored associations, put it in the array to be saved, and save them
//find previously associated Qsets, lets say it's 1,2,3 and 4 $data = array('Question'=>array('id'=>1), 'Qsets'=>array('Qsets'=>array(1,2,3,4, $new_qset)); $this->Question-save($data);
Note there's no QsetsQuestion
, since it doesn't exists. This should be the first option since the HABTM model is not complex
OR
Create
QsetsQuestion
in your model folder and change the associations as indicated above. The save part on the controller would be$data = array('qset_id'=>1, 'question_id'=>1) $this->Question->QsetsQuestion->save($data); //also works with $this->Qset->QsetsQuestion
It is much more simple (maybe), but you have to create a new file, and remember to check that there's no previous similar association (check if 2-2 tuple exists before inserting it). Simple validation rules should work.
OR
- Change cakephp behavior for this... I don't like this one.
这篇关于CakePHP:创建新的HABTM行而不是更新其他的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!