PHP/Propel удалить запись 1:n
У меня есть две таблицы: шаг и ссылки соединились 1:n. Я стремлюсь поддерживать ссылки через объекты шага. Я извлекаю все шаги из базы данных и заполняю связь таблицей ссылок. Я сохраняю объект шага, содержащий коллекцию ссылок на JSON, и возвращаю его внешнему интерфейсу с помощью REST.
Это означает, что если какой-либо шаг связан или не связан с другим шагом во внешнем интерфейсе, я отправляю весь шаг обратно в бэкэнд, включая коллекцию ссылок. В конце я использую следующий код:
public function put($processStep) {
if (isset($processStep['Processesid']) && isset($processStep['Coordx']) && isset($processStep['Coordy'])) {
$p = $this->query->findPK($processStep['Id']);
$p->setId($processStep['Id']);
$p->setProcessesid($processStep['Processesid']);
if (isset($processStep['Flowid'])) $p->setFlowid($processStep['Flowid']);
if (isset($processStep['Applicationid'])) $p->setApplicationid($processStep['Applicationid']);
$p->setCoordx($processStep['Coordx']);
$p->setCoordy($processStep['Coordy']);
$links = $p->getLinksRelatedByFromstep();
$links->clear();
foreach ($processStep['Links'] as $link) {
if (!isset($link['Linkid'])) {
$newLink = new \Link();
$newLink->setFromstep($link['Fromstep']);
$newLink->setTostep($link['Tostep']);
$links->prepend($newLink);
}
}
$p->save();
return $p;
} else {
throw new Exceptions\ProcessStepException("Missing mandatory fields.", 1);
}
}
Я в основном удаляю каждую ссылку из шага и на основе объекта запроса воссоздаю ссылки. Это избавляет меня от необходимости сравнивать, какие ссылки удаляются и добавляются. Вставка работает как брелок Propel автоматически создает новые ссылки. Дело в том, что он не удаляет, как он вставляет. Я проверил объект, который сохраняется ($p), и вижу, что ссылка удалена, но в журнале MySQL Propel не выполняет никаких действий. Похоже, что отсутствующий элемент из коллекции ссылок не вызывает грязный флаг или что-то в этом роде.
Может быть, я поступаю неправильно, надеюсь, кто-нибудь может дать какой-нибудь совет.
Спасибо
2 ответа
Благодаря Бену я оказался на правильном пути, явный вызов для удаления не нужен. Я натолкнулся на функцию с именем: setRelatedBy(ObjectCollection o). Я использую эту функцию для предоставления списка связанных объектов, новые объекты интерпретируются как вставки, а пропуски интерпретируются как удаления.
Я не нашел соответствующей документации по проблеме, вот мой код:
$p = $this->query->findPK($processStep['Id']);
$p->setId($processStep['Id']);
$p->setProcessesid($processStep['Processesid']);
$p->setCoordx($processStep['Coordx']);
$p->setCoordy($processStep['Coordy']);
if (isset($processStep['Flowid'])) $p->setFlowid($processStep['Flowid']);
if (isset($processStep['Applicationid'])) $p->setApplicationid($processStep['Applicationid']);
//Get related records, same as populaterelation
$currentLinks = $p->getLinksRelatedByFromstep();
$links = new \Propel\Runtime\Collection\ObjectCollection();
//Check for still existing links add to new collection if so.
//This is because creating a new Link instance and setting columns marks the object as dirty creating an exception due to duplicate keys
foreach ($currentLinks as $currentLink) {
foreach ($processStep['Links'] as $link) {
if (isset($link['Linkid']) && $currentLink->getLinkid() == $link['Linkid']) {
$links->prepend($currentLink);
break;
}
}
}
//Add new link objects
foreach ($processStep['Links'] as $link) {
if (!isset($link['Linkid'])) {
$newLink = new \Link();
$newLink->setFromstep($link['Fromstep']);
$newLink->setTostep($link['Tostep']);
$links->prepend($newLink);
}
}
//Replace the collection and save the processstep.
$p->setLinksRelatedByFromstep($links);
$p->save();
Чтобы удалить записи, вы всегда должны использовать delete
, diff
Метод в коллекции чрезвычайно полезен при определении того, какие объекты нужно добавить, обновить и удалить.