使用JMSSerializerBundle在symfony2中序列化前自动翻译

使用JMSSerializerBundle在symfony2中序列化前自动翻译,symfony,doctrine,jmsserializerbundle,Symfony,Doctrine,Jmsserializerbundle,在从数据库中获取实体(通过findAll())之后以及将结果序列化到json之前,我需要应用一些逻辑 我想在一些字段上添加翻译。我知道我可以通过迭代每个实体并在控制器中应用我的逻辑来手动完成。但我需要一个更好的方法 有什么建议可以让这成为一种自动的方式吗 我遇到了类似的问题,并尝试使用自定义处理程序解决此问题,但没有成功,因此我创建了编译器传递并重写JsonSerializationVisitor,其中字符串值使用TranslateableJSONSerializationVisitor类序列化

在从数据库中获取实体(通过
findAll()
)之后以及将结果序列化到
json
之前,我需要应用一些逻辑

我想在一些字段上添加翻译。我知道我可以通过迭代每个实体并在控制器中应用我的逻辑来手动完成。但我需要一个更好的方法


有什么建议可以让这成为一种自动的方式吗

我遇到了类似的问题,并尝试使用自定义处理程序解决此问题,但没有成功,因此我创建了编译器传递并重写JsonSerializationVisitor,其中字符串值使用TranslateableJSONSerializationVisitor类序列化:

namespace tkuska\DemoBundle\Serialization;
use JMS\Serializer\JsonSerializationVisitor;
use JMS\Serializer\Context; 

class TranslatableJsonSerializationVisitor extends JsonSerializationVisitor
{
    /**
     * @var \Symfony\Component\Translation\Translator;
     */
    private $translator;

    public function visitString($data, array $type, Context $context)
    {
        if (in_array('translatable', $type['params'])) {
            return (string) $this->translator->trans($data);
        }
        return (string) $data;
    }

    public function setTranslator(\Symfony\Component\Translation\Translator $translator)
    {
        $this->translator = $translator;
    }
}
和编译器:

namespace tkuska\DemoBundle\DependencyInjection\Compiler;

use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Reference;

class TranslatableJsonSerializationCompiler implements CompilerPassInterface
{
    public function process(ContainerBuilder $container)
    {
        $jmsJsonSerializationVisitor = $container->getDefinition('jms_serializer.json_serialization_visitor');
        $jmsJsonSerializationVisitor->setClass('tkuska\DemoBundle\Serialization\TranslatableJsonSerializationVisitor');

        $jmsJsonSerializationVisitor->addMethodCall('setTranslator', array(new Reference('translator')));
    }
}
在实体中,我使用参数“translateable”为类型“string”设置注释

/**
 * @VirtualProperty
 * @Groups({"details"})
 * @Type("string<'translatable'>")
 * @return order status
 */
public function getOrderStatus(){
    return 'status.ordered';
}
/**
*@VirtualProperty
*@Groups({“details”})
*@Type(“字符串”)
*@退货订单状态
*/
公共函数getOrderStatus(){
返回“status.ordered”;
}

当然,“status.ordered”是我的翻译密钥。

谢谢@zizoujab。非常有用的帖子。我对它做了一点小小的改进,调用了parent方法并取消了参数设置,这样我就可以使用这种方法来更改更复杂类型(如array)上的数据,这些类型已经有参数并已使用

/**
 * @VirtualProperty
 * @Groups({"details"})
 * @Type("string<translatable>")
 * @return order status
 */
/**
*@VirtualProperty
*@Groups({“details”})
*@Type(“字符串”)
*@退货订单状态
*/
而不是

/**
 * @VirtualProperty
 * @Groups({"details"})
 * @Type("string<'translatable'>")
 * @return order status
 */
/**
*@VirtualProperty
*@Groups({“details”})
*@Type(“字符串”)
*@退货订单状态
*/
要将字符串“translateable”转换为参数名而不是参数值,您可以像这样传递更复杂的参数,并允许我在调用父方法之前取消设置这些参数

/**
 * @VirtualProperty
 * @Groups({"details"})
 * @Type("string<translatable<set of parameters>>")
 * @return order status
 */
/**
*@VirtualProperty
*@Groups({“details”})
*@Type(“字符串”)
*@退货订单状态
*/
代码:


<?php

namespace Mktp\DefaultBundle\Service\JmsSerializer;

use JMS\Serializer\Context;
use JMS\Serializer\JsonSerializationVisitor;
use Symfony\Component\Translation\Translator;

class TranslatableJsonSerializationVisitor extends JsonSerializationVisitor
{
    /**
     * @var Translator;
     */
    private $translator;

    /**
     * @param string $data
     * @param array $type
     * @param Context $context
     * @return string
     */
    public function visitString($data, array $type, Context $context)
    {
        $translatable = $this->getParameters('translatable', $type['params']);
        if (count($translatable)) {
            $data = (string)$this->translator->trans($data);
        }
        return parent::visitString($data, $type, $context);
    }

    /**
     * @param array $data
     * @param array $type
     * @param Context $context
     * @return array|\ArrayObject|mixed
     */
    public function visitArray($data, array $type, Context $context)
    {
        $translatable = $this->getParameters('translatable', $type['params']);

        if (count($translatable)) {
            foreach ($data as $key => $value) {
                if (is_string($value)) {
                    $data[$key] = (string)$this->translator->trans($value);
                }
            }

        }
        return parent::visitArray($data, $type, $context);
    }

    /**
     * @param Translator $translator
     */
    public function setTranslator(Translator $translator)
    {
        $this->translator = $translator;
    }

    /**
     * @param string $type
     * @param array $parameters
     * @param bool $unsetParameters
     * @return array
     */
    protected function getParameters($type, &$parameters, $unsetParameters = true)
    {
        $result = array();
        foreach ($parameters as $key => $parameter) {
            if ($parameter['name'] == $type) {
                $result[] = $parameter;
                if ($unsetParameters) {
                    unset($parameters[$key]);
                }
            }
        }
        $parameters = array_values($parameters);
        return $result;
    }
}