如何在FOSRestBundle / JMS Serializer中更改字段值?

I have the field "image" in entities. But depends of action I want to show not original image, but image's preview (which I make in LiipImagineBundle). The one solution which I can imagine:

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,
    );
}

But I don't like it, because if an entity has deep children's entities the code will be very confusing.

How to do it correctly?

One possible solution is to define Handler.

Handlers allow you to change the serialization, or deserialization process for a single type/format combination.

Something like

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

        return ...;
    }
}

And register it in services.yml

serializer.handler.image_handler:
    class: FQCN\Handler\ImageHandler
    arguments: []
    tags:
        - { name: "jms_serializer.handler", type: FQCN\AdvertImage, format: json, method: serialize }

Common problem when you want to return absolute url through API while using LiipImagine and FOSRest

Change EE\TYSBundle to your own, code taken from https://github.com/EE/TellYourStoryBundle/tree/develop

JMSSerializer Handler Service with injected Cache Manager to get correct prefix

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

Handler for custom Filename type

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\Filename

<?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));
    }

}

usage of custom Filename type

/**
 * @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;

From now on you will get background_uri with absolute url to your preview Image

If i understand your question well, you need change value for correct before serialisation, i think manual can help @Accessor

class User
{
    private $id;

    /** @Accessor(getter="getTrimmedName",setter="setName") */
    private $name;

    // ...
    public function getTrimmedName()
    {
        return trim($this->name);
    }

    public function setName($name)
    {
        $this->name = $name;
    }
}