JMS序列化程序和gedmo softdeleteable不适用于关系实体

时间:2018-01-28 15:51:40

标签: symfony doctrine-orm fosrestbundle jmsserializerbundle

我正在使用Gdmo SoftDeletable过滤器用于Symfony2和Doctrine(https://github.com/l3pp4rd/DoctrineExtensions/blob/master/doc/softdeleteable.md

我也在使用JMSSerializerBundle为我的REST API序列化对JSON的响应。

如何告诉jms序列化程序注释组关于softdeleteable过滤器?

当我的回复包含与deleted_at字段不为空的实体有关系的实体时,我有错误

Entity of type 'AppBundle\Entity\Courses' for IDs id(2) was not found

因为sub_cources,示例ID 1与示例ID 2中的courses有关系,courses与id 2的关系不是空的deleted_at - 已移除的实体

例子我有

/**
 * @ORM\HasLifecycleCallbacks
 * @ORM\Table(name="sub_cources")
 *@ORM\Entity(repositoryClass="AppBundle\Entity\Repository\SubCoursesRepository")
 * @Gedmo\SoftDeleteable(fieldName="deletedAt")
 * @AssertBridge\UniqueEntity(
 *     groups={"post_sub_course", "put_sub_course"},
 *     fields="name",
 *     errorPath="not valid",
 *     message="This name is already in use."
 * )
 */
class SubCourses


    /**
 * @var Courses
 *
 * @ORM\ManyToOne(targetEntity="AppBundle\Entity\Courses", inversedBy="subCourses")
 * @Annotation\Groups({
 *     "get_sub_courses"
 * })
 * @Annotation\Type("AppBundle\Entity\Courses")
 */
private $courses;

我的行动

            return $this->createSuccessResponse(
            [
                'sub_courses' => $subCourses->getEntitiesByParams($paramFetcher),
                'total' => $subCourses->getEntitiesByParams($paramFetcher, true),
            ],
            ['get_sub_courses'],
            true
        );

我的回答看起来像

    /**
 * @param $data
 * @param null|array $groups
 * @param null|bool  $withEmptyField
 *
 * @return View
 */
protected function createSuccessResponse($data, array $groups = null, $withEmptyField = null)
{
    $context = SerializationContext::create()->enableMaxDepthChecks();
    if ($groups) {
        $context->setGroups($groups);
    }

    if ($withEmptyField) {
        $context->setSerializeNull(true);
    }

    return View::create()
        ->setStatusCode(self::HTTP_STATUS_CODE_OK)
        ->setData($data)
        ->setSerializationContext($context);
}

如何告诉jms序列化程序注释组关于softdeleteable过滤器?

1 个答案:

答案 0 :(得分:3)

我使用的解决此问题的方法是使用序列化器事件进行前后序列化。

我做的第一件事是让我的实体实现 \ Gedmo \ SoftDeleteable \ SoftDeleteable 接口。

我创建了一个容器感知的侦听器,并在pre serialize事件上检查了该对象是否可软删除。如果是,那么我禁用了可删除的软过滤器。在后期序列化中,我确保重新打开过滤器。

这仅适用于延迟加载/代理关系。如果您的关系获取设置为 EAGER ,这将无效有效

订户类别:

<?php
namespace AppBundle\Event\Subscriber;

use Gedmo\SoftDeleteable\SoftDeleteable;
use JMS\Serializer\EventDispatcher\EventSubscriberInterface as JmsEventSubscriberInterface;
use JMS\Serializer\EventDispatcher\ObjectEvent;
use Symfony\Component\DependencyInjection\ContainerInterface;

class JsonSerializerSubscriber implements JmsEventSubscriberInterface, EventSubscriberInterface
{
    /**
     * @var ContainerInterface
     */
    protected $container;

    public static function getSubscribedEvents()
    {
        return [
            [
                'event' => 'serializer.pre_serialize',
                'method' => 'onPreSerialize',
            ],
            [
                'event' => 'serializer.post_serialize',
                'method' => 'onPostSerialize',
            ],
        ];
    }

    public function onPreSerialize(ObjectEvent $objectEvent)
    {
        // before serializing; turn off soft-deleteable
        $object = $objectEvent->getObject();
        if ($object instanceof SoftDeleteable) {
            $em = $this->container->get('doctrine.orm.default_entity_manager');
            if ($em->getFilters()->isEnabled('softdeleteable')) {
                $em->getFilters()->disable('softdeleteable');
            }
        }
    }

    public function onPostSerialize(ObjectEvent $objectEvent)
    {
        // after serializing; make sure that softdeletable filter is turned back on
        $em = $this->container->get('doctrine.orm.default_entity_manager');
        if (!$em->getFilters()->isEnabled('softdeleteable')) {
            $em->getFilters()->enable('softdeleteable');
        }
    }

    /**
     * @param ContainerInterface $container
     */
    public function setContainer(ContainerInterface $container)
    {
        $this->container = $container;
    }
}

services.xml:

<services>
...
    <service id="my.serializer.event_subscriber" class="AppBundle\Event\Subscriber\JsonSerializerSubscriber">
         <call method="setContainer">
             <argument type="service" id="service_container"/>
         </call>
         <tag name="jms_serializer.event_subscriber" />
     </service>
...
</services>

实体类(以op的示例为例):

class SubCourses implements \Gedmo\SoftDeleteable\SoftDeleteable
{
...
}