CakePHP обновляет, когда он должен вставлять модель HasAndBelongsToMany
У меня есть небольшая проблема. Я создаю сайт, на котором есть теги и вопросы. У меня есть модель вопросов, модель тегов, модель QuestionsTag, все прекрасно сочетается. Пользователь, задав вопрос, помещает теги в поле, разделенное пробелом (foo bar baz), как на stackoverflow.com.
Теперь вот код для проверки, существует ли тег уже или нет, и ввода тега в базу данных и необходимых ассоциаций:
function create () {
if (!empty($this->data)) {
$this->data['Question']['user_id'] = 1;
$question = $this->Question->save ($this->data);
/**
* Preverimo če se je vprašanje shranilo, če se je,
* vprašanje označimo.
*/
if ($question) {
$tags = explode (' ', $this->data['Question']['tags']);
foreach ($tags as $tag){
if (($tagId = $this->Tag->existsByName($tag)) != false) {
/**
* Značka že obstaja, torej samo povezemo trenuten
* id z vprašanjem
*/
$this->QuestionsTag->save (array(
'question_id' => $this->Question->id,
'tag_id' => $tagId
));
}
else {
/**
* Značka še ne obstaja, jo ustvarimo!
*/
$this->Tag->save (array(
'name' => $tag
));
// Sedaj pa shranimo
$this->QuestionsTag->save(array(
'question_id' => $this->Question->id,
'tag_id' => $this->Tag->id
));
$this->Tag->id = false;
}
; }
}
}
}
Проблема в том, что вопрос имеет идентификатор 1, и я хочу, чтобы у него были теги с идентификаторами 1, 2, 3.
Когда вызываются 2-е и 3-е сохранения, Cake видит, что в таблице questions_tags уже есть вопрос с идентификатором 1, поэтому он просто обновляет тег.
Но это неверно, так как в этой таблице должно быть много вопросов с одинаковым идентификатором, так как они относятся к разным принадлежащим им тегам.
Итак, есть ли способ предотвратить это? Запретить обновление метода save?Спасибо!
3 ответа:
Это поведение не является специфичным для отношений HABTM. Вы вызываете метод
save()
внутри цикла. После первого сохранения устанавливается значениеid
, и каждый последующий вызов сохранения видит идентификатор и предполагает, что это обновление. В цикле сначала нужно вызватьmodel->create()
, чтобы сбросить значение идентификатора, которое может существовать.Из документов CakePHP в http://book.cakephp.org/view/75/Saving-Your-Data :
При вызове save в цикле не забудьте позвонить творить().
В вашем случае это выглядело бы так:
$this->QuestionsTag->create(); $this->QuestionsTag->save (array( 'question_id' => $this->Question->id, 'tag_id' => $tagId ));
Проверить сохранить все . Вы можете сделать один вызов
$this->Question->saveAll()
, и он сохранит все связанные данные, которые вы предоставляете, а также. Обратите внимание, что с данными HABTM он будет выполнятьDELETE
для любогоquestions_tags
, связанного с этимquestion_id
, а затем выполнятьINSERT
для всехtag_id
, включенных в ваши данные.
Если вы хотите убедиться, что новая запись (INSERT) сделана, а не обновление, вы можете установить
$this->create();
прямо перед вызовом save. См. http://book.cakephp.org/view/75/Saving-Your-Data (в верхней части страницы): при вызове функции save в цикле не забудьте вызвать функцию create ().