转换实体以获得较小的输出


Transform entity for smaller output

我正在尝试使用Symfony创建一个简单的日历。为此,我想通过AJAX请求所选月份的事件。每个事件可以有多个用户连接到它。

现在检索事件非常简单

    $events = $this->em->getRepository('AppBundle:Event')
            ->findByYearMonth($this->getUser(), $year, $month);
    $encoder = new JsonEncoder();
    $normalizer = new ObjectNormalizer();
    $normalizer->setCircularReferenceHandler(function ($object) {
        return $object->getId();
    });
    $serializer = new Serializer([$normalizer], [$encoder]);
    $serialized = $serializer->serialize($events, 'json');
    $response = new Response($serialized);
    $response->headers->set('Content-Type', 'application/json');

我需要setCircularReferenceHandler,因为显然用户也有连接到他们的事件。

在我的测试中,我目前只有2个事件,但我得到了大约50kb的响应,只是因为它被用户对象膨胀了。我真正想要的只是用户ID和名称,但它检索所有其他字段(以及其他连接的实体)。

循环引用处理程序本身只有在返回用户后才处于活动状态(并在最初检索用户的用户中捕获事件)。

我已经搜索过了,但没有找到一个符合我想要的结果(大多数是关于表单、通用序列化等)。

我唯一的想法是向Event实体添加一个方法,例如getSimple,在那里我手动设置一些参数并忽略outer(但对于所有连接的东西也必须这样做)。这看起来很不干净,所以我在这里问。

TL;DR

我想要像一样的东西

[
  {"id":1, "name":"foo", "users":[
    {"id":1, "name":hans"},
    {"id":2, "name":"jack"},...
  ]},...
]

但我得到了类似的东西

[
  {"id":1, "name":"foo", "users":[
    {"id":1, "name":hans", "events":[1,{"id":3, "name":"this hasnt already been shown"}], "userfield":"var", "anotheruserfield":"bar", "someOtherRelation":{"bla"},
    {"id":2, "name":"jack", "events":[1,{"id":3, "name":"this hasnt already been shown"}], "userfield":"var", "anotheruserfield":"bar", "someOtherRelation":{"bla"}},...
  ]},...
]

如果我理解正确,您希望从对象序列化中排除events属性(可能还有其他属性)。

JMSSerializer将满足您的需求,因为它允许排除/公开属性和/或限制它们的深度。

Symfony文档的"序列化"一章的末尾提到了该捆绑包。

参见排除策略及其@Exclude@Expose@Groups@MaxDepth注释。

是的,JMSSerializer提供了Exclude和其他可能解决此问题的方法,但我决定做一些不同的事情:编写一个自定义EventNormalizer,它完全符合我的要求,并且不会改变其他实体本身。

$encoder = new JsonEncoder();
$normalizer = new 'AppBundle'Serializer'Normalizer'EventNormalizer();
$serializer = new Serializer([$normalizer], [$encoder]);
$serialized = $serializer->serialize($events, 'json');

和归一化

namespace AppBundle'Serializer'Normalizer;
use Symfony'Component'Serializer'Normalizer'NormalizerInterface;
/**
 * Event normalizer
 */
class EventNormalizer implements NormalizerInterface
{
        /**
         * {@inheritdoc}
         */
        public function normalize($object, $format = null, array $context = array())
        {
                $result = /* using fields from $object */
                return $result;
        }
        /**
         * {@inheritdoc}
         */
        public function supportsNormalization($data, $format = null)
        {
                return $data instanceof 'AppBundle'Entity'Event;
        }
}