dragonmeng2002 2013-04-25 16:42
浏览 69
已采纳

CakePHP:创建新的HABTM行而不是更新其他行

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() );
}
  • 写回答

1条回答 默认 最新

  • dongzuozhu66776 2013-04-25 18:15
    关注

    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.
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 隐藏系统界面pdf的打印、下载按钮
  • ¥15 MATLAB联合adams仿真卡死如何解决(代码模型无问题)
  • ¥15 基于pso参数优化的LightGBM分类模型
  • ¥15 安装Paddleocr时报错无法解决
  • ¥15 python中transformers可以正常下载,但是没有办法使用pipeline
  • ¥50 分布式追踪trace异常问题
  • ¥15 人在外地出差,速帮一点点
  • ¥15 如何使用canvas在图片上进行如下的标注,以下代码不起作用,如何修改
  • ¥15 Windows 系统cmd后提示“加载用户设置时遇到错误”
  • ¥50 vue router 动态路由问题