Я создал набор Symfony 2, который поддерживает личные сообщения между пользователями. Я дал им возможность отправлять сообщения из своей папки inbox
или sent
на номер trash
. Сообщения будут помечены как мусор через поля isRTrash
и isSTrash
, отмеченные получателем и отправителем соответственно. Это потому, что, будучи одним и тем же сообщением в моей базе данных, если бы у меня было одно единственное поле здесь, один пользователь, отмечающий его как мусор, отметит его и для другого.Обновление определенных полей на основе условия в Doctrine
Теперь, я хочу дать им возможность также delete
из их корзины для мусора. Сообщения не будут удалены, но будут помечены аналогично мусорным, так что они навсегда исчезнут из стандартного пользовательского представления. У меня проблемы с их маркировкой, потому что я должен отмечать как сообщения, которые отправляются и принимаются пользователем.
Я сделал следующий запрос в хранилище предприятия:
public function delete($user, $msg)
{
$qb = $this->createQueryBuilder('a')
->update('PrivateMessageBundle:Message', 'a')
->where('a IN(:msg)')
->andwhere('a.receiver = :user AND a.isRTrash IS NOT null AND a.isRDeleted = false')->set('a.isRDeleted', true)
->orWhere('a.sender = :user AND a.isSTrash IS NOT null AND a.isSDeleted = false')->set('a.isSDeleted', true)
->setParameters(
array('user' => $user, 'msg' => $msg)
);
echo '<pre>';
\Doctrine\Common\Util\Debug::dump($qb->getQuery()->getSQL()); exit;
echo '</pre>';
return $qb->getQuery();
}
И выход запрос string(196) "UPDATE message SET isRDeleted = 1, isSDeleted = 1 WHERE (id IN (?) AND (receiver_id = ? AND isRTrash IS NOT NULL AND isRDeleted = 0)) OR (sender_id = ? AND isSTrash IS NOT NULL AND isSDeleted = 0)"
я даю в качестве входа curent зарегистрированного пользователя и массив идентификаторов сообщения. Затем я проверяю сообщения, которые находятся в корзине, не помечены как удаленные и не имеют текущего пользователя в качестве получателя или отправителя и хотят пометить их как удаленные.
Проблема заключается в том, что оба условия выполнены, и вызываются как SET
, маркируя isRDeleted
сообщения, так и isSDeleted
истинным, независимо.
Я очень близко, но не знаю, как это сделать, чтобы поля отмечены отдельно, только если их условие выполнено.
Между тем, я использую цикл Еогеасп, но я думаю, что это можно сделать быстрее с помощью запроса
$em = $this->getDoctrine()->getManager();
foreach ($msgs as $msgid) {
$msg = $messages->findOneBy(array('id' => $msgid));
if ($msg->getSender() == $this->getUser() && $msg->getIsSTrash() && $msg->getIsSDeleted() == false) {
$msg->setIsSDeleted(true);
$changedno++;
} else if ($msg->getReceiver() == $this->getUser() && $msg->getIsRTrash() && $msg->getIsRDeleted() == false) {
$msg->setIsRDeleted(true);
$changedno++;
}
$em->flush();
}
Да, я понял, что порядок не имеет значения в запросе. Я также искал инструкции CASE..WHEN, но не могу найти никаких рабочих решений для UPDATE, только для INSERT. –
Не должны ли вы оставить значения isR/SDeleted без изменений, если условия не выполняются? Похоже, вы можете воскрешать сообщения по ошибке;). Не понимаю, почему вам нужно проверить, являются ли значения ложными, поскольку вы все равно установите их в true, какое влияние на производительность? –
@GeorgeIrimiciuc вам просто нужно использовать собственный SQL-запрос в Doctrine: 'return $ this-> getEntityManager() -> getConnection() -> executeQuery ($ sql, $ params);' с '$ sql' ваш запрос и' $ params' параметры. – tchap