CakePHP: создание новой строки HABTM вместо обновлений

У меня две модели с отношением HABTM (имеет и принадлежит многим): 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 

update : Вот дамп моей таблицы 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() ); } 

Хорошо, вот что я думаю, что происходит:

Вы не используете супер полезную магию отношения HABTM. Вместо того, чтобы рассматривать эту таблицу как обычную таблицу отношений, торт переходит к определенной модели, а видит отношения, которые вы определили, и primaryKeys и displayFields и т. Д.

Это нормально, когда у вас сложная таблица HABTM. Но если это так, ваш массив данных все испорчен, потому что вы не добавляете Question и Qset отдельно. Я имею в виду, что вы не делаете

 $data = array('Question'=>array('title'=>'new_question'), 'Qset'=>array('name'=>'lets 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, с новым отношением, как и вы.

Однако будьте осторожны, так как вы используете свою собственную модель для этого, если вы не правильно настроили правильность, вы можете иметь одну и ту же пару внешних ключей много раз, потому что по умолчанию торт просто проверяет, что идентификатор должен быть уникальным ,

[РЕДАКТИРОВАТЬ] После небольшого уточнения решение выше решит «проблему», но на самом деле это не причина такого поведения.

CakePHP имеет функцию

По умолчанию при сохранении отношений HasAndBelongsToMany Cake удалит все строки в таблице соединений, прежде чем сохранять новые. Например, если у вас есть Клуб, в котором есть 10 детей. Затем вы обновляете Клуб с 2 детьми. В клубе будет всего 2 ребенка, а не 12.

Поэтому, когда вы хотите добавить новую строку, торт удаляет все предыдущие ассоциации и добавляет новые. Способ решить это – найти все Qsets которые принадлежат к вопросу, и добавить их в массив $data (с добавлением новой ассоциации вопросов, которую вы хотите добавить). Эта ссылка помогла мне понять ассоциации HABTM (ищите «Challenge IV»).

Я знаю, что решение, которое я дал, помогло вам с «проблемой», но это было сделано под впечатлением, что у вас был QsetsQuestion модели 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 для этого … Мне это не нравится.