Как изменить значение поля в FOSRestBundle/JMS Serializer?

У меня есть поле "изображение" в сущностях. Но в зависимости от действия я хочу показать не исходное изображение, а превью изображения (которое я делаю в LiipImagineBundle). Единственное решение, которое я могу себе представить:

public function cgetAction(Request $request)
{
    $events = $this->container->get('gc.event_manager')->getEvents();
    foreach ($events as &$event) {
        $previewURL = $this->getPreview($event->getPhoto());
        $event->setPhoto($previewURL);
    }
    $event = false;

    return array(
        'events' => $events,
    );
}

Но мне это не нравится, потому что если у сущности есть глубокие дочерние сущности, код будет очень запутанным.

Как это сделать правильно?


person Сергей Студеникин    schedule 05.09.2013    source источник


Ответы (2)


Распространенная проблема, когда вы хотите вернуть абсолютный URL-адрес через API при использовании LiipImagine и FOSRest.

Измените EE\TYSBundle на свой собственный, код взят с https://github.com/EE/TellYourStoryBundle/tree/develop

Служба обработчика JMSSerializer с внедренным диспетчером кеша для получения правильного префикса

ee_tys.serializer.filename_handler:
    class: EE\TYSBundle\Handler\FilenameHandler
    arguments:
        - "@liip_imagine.cache.manager"
    tags:
        - { name: 'jms_serializer.handler', type: Filename, format: json}

Обработчик пользовательского типа имени файла

EE\TYSBundle\Handler\FilenameHandler.php

<?php

namespace EE\TYSBundle\Handler;

use EE\TYSBundle\Entity\Filename;
use JMS\Serializer\GraphNavigator;
use JMS\Serializer\Handler\SubscribingHandlerInterface;
use JMS\Serializer\VisitorInterface;
use Liip\ImagineBundle\Imagine\Cache\CacheManager;

class FilenameHandler implements SubscribingHandlerInterface
{

    function __construct(CacheManager $manager)
    {
        $this->manager = $manager;
    }


    public static function getSubscribingMethods()
    {
        return array(
            array(
                'direction' => GraphNavigator::DIRECTION_SERIALIZATION,
                'format' => 'json',
                'type' => 'Filename',
                'method' => 'serializeFilenameToJson',
            ),
        );
    }

    public function serializeFilenameToJson(VisitorInterface $visitor, Filename $filename, array $type)
    {
        // `tile` is a name of Imagine filter you want to apply
        return $this->manager->getBrowserPath($filename, 'tile', true);
    }
}

EE\TYSBundle\Entity\Имя файла

<?php

namespace EE\TYSBundle\Entity;

/**
 * Class Filename
 * @package EE\TYSBundle\Entity
 */
class Filename {

    /**
     * @var string
     */
    public $name;

    /**
     * @var string
     */
    public $extension;

    public function __construct($filename)
    {
        $parts = explode(".", $filename);

        $this->setName($parts[0]);

        $this->setExtension($parts[1]);

    }

    /**
     * @param mixed $extension
     * @return Media
     */
    public function setExtension($extension)
    {
        $this->extension = $extension;

        return $this;
    }

    /**
     * @return mixed
     */
    public function getExtension()
    {
        return $this->extension;
    }

    /**
     * @param mixed $name
     * @return Filename
     */
    public function setName($name)
    {
        $this->name = $name;
    }

    /**
     * @return mixed
     */
    public function getName()
    {
        return $this->name;
    }

    /**
     * @return string filename
     */
    public function __toString()
    {
        return join(".", array($this->name, $this->extension));
    }

}

использование пользовательского типа имени файла

/**
 * @var string|null
 *
 * @ORM\Column(name="background_filename", type="string", length=255, nullable=true)
 *
 * @Serializer\Expose
 * @Serializer\Type("Filename")
 * @Serializer\SerializedName("background_uri")
 */
private $backgroundFilename;

С этого момента вы получите background_uri с абсолютным URL-адресом вашего изображения для предварительного просмотра.

person Konrad Podgórski    schedule 23.09.2013

Одним из возможных решений является определение Handler.

Обработчики позволяют изменить процесс сериализации или десериализации для одной комбинации типа/формата.

Что-то типа

class ImageHandler
{
    public function serialize(VisitorInterface $visitor, \FQCN\Image $image, array $type, Context $context)
    {
        // do some stuff

        return ...;
    }
}

И зарегистрируйте его в services.yml

serializer.handler.image_handler:
    class: FQCN\Handler\ImageHandler
    arguments: []
    tags:
        - { name: "jms_serializer.handler", type: FQCN\AdvertImage, format: json, method: serialize }
person Alexey B.    schedule 05.09.2013
comment
Спасибо большое за столь подробный ответ! - person Сергей Студеникин; 06.09.2013