Intereting Posts
Один блок вызова ajax другой вызов ajax Force PDF скачать с PHP – файл поврежден в Windows Удаление любого существующего файла из Dropzone показывает dictDefaultMessage Как я могу использовать буферизацию var_dump + output без ошибок памяти? PHP-код для преобразования MySQL-запроса в CSV Невозможно ограничить действия пользователя после успешного входа в codeigniter buddypress bp_core_add_message () не запускает почему? Почему моя функция GET моего API REST не возвращает никакого значения? Почему PHP 5.2+ запрещает использование абстрактных методов статического класса? Создание PDF с использованием TCPDF при вызове ajax Как добавить значения REQUEST к методу HTTP POST с помощью multipart для загрузки файла на PHP-сервер в Android? dompdf изображение не настоящее изображение не читаемое или пустое Как получить целое число между двумя значениями из потока бит? Как зашифровать открытый текст с AES-256 CBC в PHP с помощью openssl ()? Как получить HTTP_REFERER из Yahoo или Gmail

Есть ли способ сделать saveAll () удалить посторонние объекты?

У моего объекта-хозяина есть связанные с ним объекты-опции. В форме редактирования пользователи могут (де) выбирать параметры и сохранять этот новый набор ассоциаций. Это реализовано с помощью saveAll () для опубликованных данных. В результате

  • хост (основной) объект обновляется,
  • (ассоциированные) объекты, которые включены как в предыдущую, так и в новую ассоциацию, обновляются и
  • объекты опций, которые не были включены в предыдущую ассоциацию, но включены в новую.

Но чего не происходит

  • эти объекты объектов, которые были включены в предыдущую ассоциацию, но не в новую, удалены.

Вопрос: Может ли saveAll () сделать это, и как структура данных должна выглядеть так, чтобы достичь этого эффекта?

Связанная информация:

Мой код для обработки формы редактирования на самом деле более сложный (следовательно, я не цитировал его здесь), но он приводит к структуре данных, как описано в книге:

( [Host] => ( ... host object fields ... ), [Option] => ( [0] => ( ... first option object fields ... ), ... [n] => ( ... nth option object fields ... ) ) ) 

Теперь, если исходный хост имел связанную опцию, которая не включена в массив 0..n, тогда saveAll () не обнаружит этого и не удалит связанный объект.

Не уверен, что это актуально, но я использую CakePHP 1.3.

Solutions Collecting From Web of "Есть ли способ сделать saveAll () удалить посторонние объекты?"

HABTM удаляет все связанные записи, а затем воссоздает то, что необходимо. Как предлагает PawelMysior , вы можете добиться этого с помощью hasMany , вручную удалив связанные записи непосредственно перед сохранением. Однако опасность состоит в том, что сохранение не позволяет вам потерять предыдущее состояние.

Я пошел бы с вариантом решения GJ и удалял их после успешного сохранения, но вместо этого перебирал массив избыточных идентификаторов и использовал метод Cake's Model-> del (). Таким образом, вы сохраняете всю встроенную обработку ошибок.

Не очень элегантное решение, но работает для меня.

 if ($this->Main->saveAll($this->data)) { $this->Main->query(sprintf( 'DELETE ' . 'FROM extraneous ' . 'WHERE main_id = \'%s\' AND modified < (SELECT modified FROM main WHERE id = \'%1$s\')' , mysql_real_escape_string($this->Main->id) )); } 

Обратите внимание, что ваши таблицы должны иметь модифицированное поле.

Вы можете гарантировать, что все будет выполняться атомарно, если вы вручную обернете все в транзакцию.

Это можно сделать с помощью методов begin() , rollback() и commit() источника данных:

 $this->Main->begin(); if ( !$this->Main->save(...) ) { $this->Main->rollback(); return false; } // Perform saves in related models... if ( !$this->Main->MainRelatedModel->save(...) ) { $this->Main->rollback(); return false; } // Perform deletes in extraneous records... if ( !$this->Main->MainRelatedModel->delete(...) ) { $this->Main->rollback(); return false; } // Everything went well, commit and close the transaction $this->Main->commit(); 

Основным недостатком здесь является то, что транзакции не могут быть вложенными, поэтому вы не можете использовать saveAll() . Вы должны сохранять / удалять все шаг за шагом, а не делать это за один раз.

saveAll() удалит что-либо из вашей базы данных.

Я думаю, лучший способ – удалить параметры, связанные с текущим хостом перед сохранением, а затем добавить их. Если, однако, вам необходимо обновить те, которые уже существуют (вы?) По какой-либо причине (например: параметры связаны с некоторыми другими моделями), я думаю, вы можете попытаться написать фрагмент кода, который удалит невыбранные параметры.

Глядя на это, я заметил, что до сих пор не существует встроенного в CakePHP решения. Для этого я добавил следующий код в мою модель:

 private $oldBarIds = array(); public function beforeSave($options = array() { parent::beforeSave($options); $this->oldBarIds = array(); if ($this->id && $this->exists() && isset($this->data['Bar'])) { $oldBars = $this->Bar->find('all', array( 'fields' => array('id'), 'conditions' => array( 'Bar.foo_id' => $this->id ) )); $this->oldBarIds = Hash::extract($oldBars, '{n}.id'); } } 

Это проверяет наличие Bar в данных сохранения. Если это произойдет, он получит текущий идентификатор текущих, установив их в $this->oldBarIds . Затем, когда сохранение будет успешным, оно должно удалить старые:

 public function afterSave($created, $options = array()) { parent::afterSave($created, $options); if (!$created && $this->oldBarIds) { $this->Bar->deleteAll(array( 'Bar' => $this->oldBarIds )); } } 

Таким образом, удаление обрабатывается моделью и происходит только тогда, когда сохранение выполнено успешно. Должен иметь возможность добавить это к поведению, может сделать это когда-нибудь.