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

时间:2016-04-07 17:18:52

标签: php symfony

我正在尝试使用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,我手动设置一些参数并将其输出(但必须为连接的所有内容执行此操作)。这看起来很不干净,因此我在这里问。

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"}},...
  ]},...
]

2 个答案:

答案 0 :(得分:0)

如果我正确理解,您希望从对象序列化中排除class Foo { public int Bar { get; set; } } var source = new List<Foo>(); bool test1 = !source.Any() || source.All(e => e.Bar == 0); bool test2 = source.All(e => e.Bar == 0); bool test3 = !source.Any(e => e.Bar == 0); Debug.Assert(test1 == test2 && test2 == test3); 属性(可能还有其他属性)。

JMSSerializer可以满足您的需求,因为它允许排除/暴露属性和/或限制其深度。

在Symfony文档的Serialization chapter末尾提到了该包。

请参阅exclusion strategies及其events@Exclude@Expose@Groups注释。

答案 1 :(得分:0)

是的,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;
        }
}