我知道Doctrine的扩展可以管理树/嵌套集的行为,但这似乎对我想要的功能来说是非常过分的。
我只是有一个名为Faq
的模型,其中包含字段question
,answer
和number
,createdAt
和updatedAt
。 number
列用于编辑问题在页面上的显示顺序。
我正在使用EasyAdminBundle
提供一个简单的管理面板,供我的客户编辑FAQ。
现在是这样,假设有5个问题,客户希望将第5个问题设为第3个问题。我想要的是,他只需用值number
编辑第五个问题的3
字段,其他实体的所有其他number
字段都会自动适应此更改。所以3和4现在分别变成4和5。
我假设我需要某种事件侦听器,但我不太清楚哪种类型。
到目前为止,我只知道一旦有了正确的事件侦听器,我就应该在执行它时执行此操作:
function updateNumbers(EntityManagerInterface $em)
{
$faqRepo = $em->getRepository(Faq::class);
$faqs = $faqRepo->findAll();
// ^ that is already correctly sorted, based on number and updatedAt
foreach($faqs as $i => $faq) {
$faq->setNumber($i+1);
}
$em->flush();
}
现在,我只需要知道如何确保在正确的时刻触发该功能即可。有帮助吗?
答案 0 :(得分:0)
使用您编写的代码,您甚至可能甚至应该使用postFlush
,但是请注意,从事件监听器调用$em->flush()
会再次触发事件,因此您需要一个递归保护器。您可能还想编写其他逻辑,仅当某些职位的位置确实发生变化时才运行重新索引逻辑。
对于稍微简单的方法,您可以加入preUpdate
事件。当某个条目的number
发生更改时,您将触发一个数据库查询,该查询将更新number
大于或等于新值的所有条目,并将它们的number
增加1。
答案 1 :(得分:0)
好的,我通过执行以下操作解决了该问题:
// src/EventListener/FaqSorter.php
namespace App\EventListener;
use App\Entity\Faq;
use Doctrine\ORM\Mapping as ORM;
use App\Repository\FaqRepository;
use Doctrine\ORM\Event\LifecycleEventArgs;
class FaqSorter
{
/**
* @ORM\PrePersist
* @ORM\PostUpdate
* @ORM\PostRemove
*/
function updateNumbers(Faq $faq, LifecycleEventArgs $event)
{
static $hasRun = false;
// This is not the prettiest solution to prevent recurrence,
// but AFAIK I never need to run this more than once per request.
if ($hasRun) return;
$em = $event->getEntityManager();
/** @var FaqRepository $faqRepo */
$faqRepo = $em->getRepository(get_class($faq));
$faqs = $faqRepo->findAll();
// ^ that is already correctly sorted, based on number and updatedAt
if ($faq->getNumber() === null) {
// If the number was null then this was triggered
// by a PrePersist event and then I'll just
// put it at the end of the list.
return $faq->setNumber(count($faqs) + 1);
}
foreach($faqs as $i => $faq) {
$faq->setNumber($i+1);
}
$hasRun = true;
$em->flush();
}
}
然后在config/services.yaml
中输入:
services:
# ...
App\EventListener\FaqSorter:
tags:
- { name: doctrine.orm.entity_listener }
在src/Entity/Faq.php
中:
namespace App\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* @ORM\Entity(repositoryClass="App\Repository\FaqRepository")
* @ORM\EntityListeners({"App\EventListener\FaqSorter"})
*/
class Faq {
// ...
}