symfony - 动态删除 JMS 序列化程序事件订阅者内的实体

标签 symfony doctrine-orm jmsserializerbundle

我有一个 Doctrine 实体,我使用 JMS 序列化程序在我的 API 中呈现它。

我想添加一个这样的 bool 字段:

/**
 * @var bool
 *
 * @ORM\Column(name = "is_serialized", type = "boolean")
 */
protected $isSerialized = true;

我还使用 EventSubscriber 在序列化之前向我的实体添加一些数据。

我想根据 $isSerialized 动态包含或不包含每个实体值(我无法修改 Doctrine 查询)。
class SerializationEventSubscriber extends EventSubscriberInterface
{
    /**
     * @param ObjectEvent $event
     */
    public function onPostSerialize(ObjectEvent $event)
    {
        if (!$this->isGroup('api', $event)) {
            return;
        }

        $entity  = $event->getObject();
        $visitor = $event->getVisitor();

        if (!$object->isSerialized()) {
            // Skip the current object and remove it from serialization
        }
    }
}

我在 JMS 注释文档中都找不到关于此的任何信息。

最佳答案

这是我的 EventListener ,但我没有删除对象,而是跳过了空字段。

use Doctrine\ORM\Mapping\ClassMetadata;
use Doctrine\ORM\EntityManagerInterface;
use JMS\Serializer\JsonSerializationVisitor;
use JMS\Serializer\EventDispatcher\ObjectEvent;
use JMS\Serializer\Metadata\ClassMetadata as JMSClassMetadata;
use JMS\Serializer\Metadata\StaticPropertyMetadata;

class EntitySerializerListener
{
    /**
     * @var EntityManagerInterface
     */
    protected $em;

    public function __construct(EntityManagerInterface $entityManager)
    {
        $this->em = $entityManager;
    }

    public function onPostSerialize(ObjectEvent $event)
    {
        /** @var JsonSerializationVisitor $visitor */
        $object = $event->getObject();
        $visitor = $event->getVisitor();
        $context = $event->getContext();
        $type = $event->getType();

        /** @var JMSClassMetadata $metadata */
        $metadata = $context->getMetadataFactory()->getMetadataForClass($type['name']);

        $data = $visitor->endVisitingObject($metadata, $object, $type);
        $visitor->startVisitingObject($metadata, $object, $type);

        // Here I remove unnecessary fields
        $this->prune($type['name'], $data);
 
        // Reset fresh serialized data
        foreach ($data as $field => $value) {
            $visitor->visitProperty(new StaticPropertyMetadata($type['name'], $field, $value), $value);
        }
    }

    /**
     * Prune the empty field which was set to NULL by MaxDepth annotation but left in the data graph by JWT serializer.
     *
     * @param string $fqcn
     * @param array $data
     */
    protected function prune(string $fqcn, array & $data)
    {
        /** @var ClassMetadata $metadata */
        $metadata = $this->em->getMetadataFactory()->getMetadataFor($fqcn);

        // Handle association
        $associations = $metadata->getAssociationMappings();
        foreach ($associations as $field => $association) {
            if (!array_key_exists($field, $data)) {
                continue;
            }
            
            // Here remove entity or any other field which you want
            if (empty($data[$field])) {
                unset($data[$field]);
            } else {
                $this->prune($association['targetEntity'], $data[$field]);
            }
        }
    }
}

关于symfony - 动态删除 JMS 序列化程序事件订阅者内的实体,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42621810/

相关文章:

mysql - Symfony2 和 Doctrine : how to use findOneBy method taking capitals into account

php - 在 Symfony 3 中组织模型

php - 交响乐 2 : Access updated configuration from inside a command

symfony - 选择使用不在索引中的字段的 where 子句返回 : Binding an entity with a composite primary key to a query is not supported

php - 交响乐/独白 : Custom processor with FOSUserBundle data

php - Composer 更新 => fatal error : Out of memory

使用相同属性路径的 Symfony2 嵌入式表单 - 错误冒泡问题

symfony - JMSSerializerBundle 复杂生成值

symfony - @JMS\仅当属性为空时排除

symfony - 您请求了一个不存在的服务 "jms_serializer"