3

私は、HABTM (多くに属し、多数に属している) 関係を持つ 2 つのモデルを持っています: Qsets と Questions です。

次のアクション (QsetsController.php 内) により、qsets_questions テーブルに新しい行が作成され、新しい質問が新しい qset に表示されます。ただし、代わりに既存の行を更新するため、その質問が以前の qset から取得され、新しいものに追加されます。

私は何を間違っていますか?

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() );
}

私の説明からは明らかでない場合は、次のことが起こります。

質問を追加する前に...

**Qset 1**
Question 1
Question 2

**Qset 2**
Question 3
Question 4

質問 2 を Qset 2 に追加するとどうなる

**Qset 1**
Question 1
Question 2

**Qset 2**
Question 3
Question 4
Question 2

逆にどうなるか…

**Qset 1**
Question 1
          <----removed
**Qset 2**
Question 3
Question 4
Question 2

更新: これは私の qsets_questions テーブルのダンプです:

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 ;

解決:

@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() );
}
4

1 に答える 1

3

わかりました、これが私が起こっていると思うことです:

非常に便利な HABTM リレーション マジックを使用していません。このテーブルを単なるリレーション テーブルとして扱う代わりに、cake は定義されたモデルに移動し、定義したリレーション、primaryKeys、displayFields などを確認します。

複雑な HABTM テーブルがある場合は問題ありません。しかし、その場合、データ配列はすべて台無しになります。なぜなら、QuestionとをQset別々に追加していないからです。私が言いたいのは、あなたがしていないということです

$data = array('Question'=>array('title'=>'new_question'),
              'Qset'=>array('name'=>'lets say qset'));
$this->Question->saveAll($data);

そうすることで、cake に HABTM の関連付けを解決させることができ、そのデータ構造は問題ありません。しかし、モデル フォルダに独自の QsetsQuestion モデルがあります。したがって、保存するデータは、他のテーブルと同じようにする必要があります。

$data = array('qset_id'=> $qset_id,
              'question_id'=> $question_id);
$this->Question->QsetsQuestion->save($data);

そして、それはあなたが望むように、新しいリレーションで qsets_questions テーブルに新しい id を作成します。

ただし、これには独自のモデルを使用しているため、検証を正しく設定しないと、同じ外部キーのペアが何度も発生する可能性があることに注意してください。デフォルトでは、ケーキはIDが一意でなければならないことを確認するだけだからです.

[編集] 少し明確にした後、上記の解決策は「問題」を解決しますが、実際にはこの動作の理由ではありません。

Cakephpには機能があります

デフォルトでは、HasAndBelongsToMany 関係を保存するとき、Cake は新しい行を保存する前に結合テーブルのすべての行を削除します。たとえば、10 人の子供が関連付けられているクラブがあるとします。次に、Club を 2 つの子で更新します。クラブには12人ではなく、2人の子供しかいません。

したがって、新しい行を追加する場合、cake は以前の関連付けをすべて削除し、新しい関連付けを追加します。これを解決する方法はQsets、質問に属するすべての を見つけて$data配列に追加することです (追加する新しい質問の関連付けを追加して)。このリンクは、HABTM の関連付けを理解するのに役立ちました (「チャレンジ IV」を探してください)。

以前に提供した解決策が「問題」の解決に役立ったことは知っていますが、QsetsQuestionモデルファイルがどこかにあるという印象の下で作成されました。そうでないので、解決策はすべてをQuestions関連付けて新しい配列として追加することです。または、実際にQsetsQuestionモデルを作成し、次のように関連付けを行います。

Qset hasMany QsetsQuestion
QsetsQuestion belongsTo Qset, Question
Question hasMany Qsets.

または、ケーキの動作を変更します...どれもきれいに見えません。

したがって、ソリューションの要約:

  • 新しい Qset-Question 関連付けを保存するたびに、以前に保存された関連付けを取得し、それを保存する配列に入れて保存します。

    //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);
    

存在しないので、ないことに注意してくださいQsetsQuestion。HABTM モデルは複雑ではないため、これが最初のオプションです。

また

  • モデル フォルダーに作成QsetsQuestionし、上記のように関連付けを変更します。コントローラーの保存部分は次のようになります

    $data = array('qset_id'=>1, 'question_id'=>1)
    $this->Question->QsetsQuestion->save($data);    //also works with $this->Qset->QsetsQuestion
    

はるかに単純ですが (おそらく)、新しいファイルを作成する必要があり、以前に同様の関連付けがないことを確認することを忘れないでください (挿入する前に 2-2 タプルが存在するかどうかを確認してください)。単純な検証ルールが機能するはずです。

また

  • これに合わせて Cakephp の動作を変更してください... 私はこれが好きではありません。
于 2013-04-25T18:15:38.393 に答える