Symfony 4 序列化没有关系的实体 [英] Symfony 4 serialize entity without relations

查看:77
本文介绍了Symfony 4 序列化没有关系的实体的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我必须记录每个实体的变化.我有侦听 preRemovepostUpdatepostDelete 上的学说事件的监听器.我的实体 AccessModule 有关系:

App\Entity\AccessModule.php

/*** @ORM\OneToMany(targetEntity=App\Entity\AccessModule",mappedBy=parent")* @ORM\OrderBy({id"=ASC"})*/私人 $children;/*** @ORM\ManyToOne(targetEntity=App\Entity\AccessModule", inversedBy=children")* @ORM\JoinColumn(name=parent_id", referencedColumnName=id", nullable=true)*/私人 $parent;/*** @ORM\ManyToMany(targetEntity=App\Entity\AccessModuleRoute", inversedBy=access_modules")* @ORM\JoinTable(name=access_routes",* joinColumns={@ORM\JoinColumn(name=access_module_id", referencedColumnName=id")},* inverseJoinColumns={@ORM\JoinColumn(name=route_id", referencedColumnName=id")})**/私人 $routes;

在监听器中:App\EventListener\EntityListener.php

使用 Symfony\Component\Serializer\Encoder\JsonEncoder;使用 Symfony\Component\Serializer\Encoder\XmlEncoder;使用 Symfony\Component\Serializer\Normalizer\ObjectNormalizer;$encoders = [new XmlEncoder(), new JsonEncoder()];$normalizer = new ObjectNormalizer();$normalizer->setCircularReferenceHandler(function ($object) {返回 $object->getId();});$this->serializer = new Serializer([$normalizer], $encoders);公共函数 createLog(LifecycleEventArgs $args, $action){$em = $args->getEntityManager();$entity = $args->getEntity();if ($this->tokenStorage->getToken()->getUser()) {$username = $this->tokenStorage->getToken()->getUser()->getUsername();} 别的 {$用户名 = '匿名';//TODO 删除匿名.设置空值}$log = 新日志();//$log->setData('dddd')$log->setData($this->serializer->serialize($entity, ''json)->setAction($action)->setActionTime(new \DateTime())->setUser($username)-> setEntityClass(get_class($entity));$em->persist($log);$em->flush();}

我有序列化问题当我使用 $log->setData($entity) 时,我遇到了 Circular 问题.当我做序列化 $log->setData($this->serializer->serialize($entity, ''json) 我充满了关系,与父母的孩子,与孩子的孩子.结果我得到了完整的树:/我想得到

期待

<预><代码>['id' =>ID,'名称' =>名称,'父母' =>parent_id//ManyToOne,我想得到它的 id'孩子' =>[$child_id, $child_id, $child_id]//子数组集合的 $id 数组]

(当然这是在编码为json之前的草稿)

如何在没有完整关系的情况下获得预期数据?

解决方案

你要找的东西叫做序列化组:这里这里.

现在让我解释一下它是如何工作的.这很简单.假设您有发布实体:

class Post{/*** @ORM\Id* @ORM\GeneratedValue* @ORM\Column(type="整数")* @Groups({"default"})*/私人 $id;/*** @ORM\ManyToOne(targetEntity="App\Entity\User\User")* @Groups({"default"})*/私人 $author;}

你还有用户实体:

类用户{/*** @ORM\Id* @ORM\GeneratedValue* @ORM\Column(type="整数")* @Groups({"default"})*/私人 $id;/*** @ORM\Column(type="string", length=40)* @Groups({"default"})*/私人 $firstName;/*** @ORM\Column(type="string", length=40)*/私人 $lastName;}

帖子可以有作者(用户),但我不想每次都返回所有用户数据.我只对 ID 和名字感兴趣.

仔细查看 @Groups 注释.您可以指定所谓的序列化组.这只不过是告诉 Symfony 您希望在结果集中包含哪些数据的便捷方式.

您必须通过在属性/getter 上方以注释的形式添加相关组来告诉 Symfony 序列化程序您希望保留哪些关系.您还必须指定要保留的关系的哪些属性或 getter.

现在如何让 Symfony 知道这些东西?

当您准备/配置您的序列化服务时,您只需提供如下定义的组:

return $this->serializer->serialize($data, 'json', ['groups' => ['default']]);

围绕原生 symfony 序列化程序构建某种包装服务是很好的,这样您就可以简化整个过程并使其更可重用.

还要确保正确配置了序列化程序 - 否则它不会考虑这些组.

这也是处理"循环引用的一种方式(以及其他方式).

现在您只需要研究如何格式化结果集.

I have to log the changes of each entity. I've Listener which listens for doctrine's events on preRemove, postUpdate and postDelete. My entity AccessModule has relations:

App\Entity\AccessModule.php

/**
 * @ORM\OneToMany(targetEntity="App\Entity\AccessModule", mappedBy="parent")
 * @ORM\OrderBy({"id" = "ASC"})
 */
private $children;

/**
 * @ORM\ManyToOne(targetEntity="App\Entity\AccessModule", inversedBy="children")
 * @ORM\JoinColumn(name="parent_id", referencedColumnName="id", nullable=true)
 */
private $parent;

/**
 * @ORM\ManyToMany(targetEntity="App\Entity\AccessModuleRoute", inversedBy="access_modules")
 * @ORM\JoinTable(name="access_routes",
 *     joinColumns={@ORM\JoinColumn(name="access_module_id", referencedColumnName="id")},
 *     inverseJoinColumns={@ORM\JoinColumn(name="route_id", referencedColumnName="id")})
 *
 */
private $routes;

in listener: App\EventListener\EntityListener.php

use Symfony\Component\Serializer\Encoder\JsonEncoder;
use Symfony\Component\Serializer\Encoder\XmlEncoder;
use Symfony\Component\Serializer\Normalizer\ObjectNormalizer;


    $encoders = [new XmlEncoder(), new JsonEncoder()];
    $normalizer = new ObjectNormalizer();

        $normalizer->setCircularReferenceHandler(function ($object) {
            return $object->getId();
        });

    $this->serializer = new Serializer([$normalizer], $encoders);


public function createLog(LifecycleEventArgs $args, $action){
    $em = $args->getEntityManager();
    $entity = $args->getEntity();
    if ($this->tokenStorage->getToken()->getUser()) {
        $username = $this->tokenStorage->getToken()->getUser()->getUsername();
    } else {
        $username = 'anon'; // TODO Remove anon. set null value
    }

    $log = new Log();
//      $log->setData('dddd')
        $log->setData($this->serializer->serialize($entity, ''json)
            ->setAction($action)
            ->setActionTime(new \DateTime())
            ->setUser($username)
            ->setEntityClass(get_class($entity));
        $em->persist($log);
        $em->flush();
    }

I've problem with serialization When I use $log->setData($entity) I get problem with Circular. Whan I do serialization $log->setData($this->serializer->serialize($entity, ''json) I get full of relations, with parent's children, with children children. In a result I get full tree :/ I'd like to get

Expect

[
 'id' => ID,
 'name' => NAME,
 'parent' => parent_id // ManyToOne, I'd like get its id
 'children' => [$child_id, $child_id, $child_id] // array of $id of children array collection
]

(ofcourse this is draft before encode it to json)

How can I get expected data without full relations?

解决方案

Thing you are looking for is called serialization groups: here and here.

Now let me explain how it works. It's quite simple. Say you have Post Entity:

class Post
{
    /**
     * @ORM\Id
     * @ORM\GeneratedValue
     * @ORM\Column(type="integer")
     * @Groups({"default"})
     */
    private $id;

    /**
     * @ORM\ManyToOne(targetEntity="App\Entity\User\User")
     * @Groups({"default"})
     */
    private $author;
}

And you have also User Entity:

class User
{
    /**
     * @ORM\Id
     * @ORM\GeneratedValue
     * @ORM\Column(type="integer")
     * @Groups({"default"})
     */
    private $id;

    /**
     * @ORM\Column(type="string", length=40)
     * @Groups({"default"})
     */
    private $firstName;

    /**
     * @ORM\Column(type="string", length=40)
     */
    private $lastName;
}

Post can have author(User) but I don't want to return all User data every single time. I'm interested only in id and first name.

Take a closer look at @Groups annotation. You can specify so called serialization groups. It's nothing more than convinient way of telling Symfony which data you would like to have in your result set.

You have to tell Symfony serializer which relationships you would like to keep by adding relevant groups in form of annotation above property/getter. You also have to specify which properties or getters of your relationships you would like to keep.

Now how to let Symfony know about that stuff?

When you prepare/configure your serializaition service you just simply have to provide defined groups like that:

return $this->serializer->serialize($data, 'json', ['groups' => ['default']]);

It's good to build some kind of wrapper service around native symfony serializer so you can simplify the whole process and make it more reusable.

Also make sure that serializer is correctly configured - otherwise it will not take these group into account.

That is also one way(among other ways) of "handling" circular references.

Now you just need to work on how you will format your result set.

这篇关于Symfony 4 序列化没有关系的实体的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆