Search code examples
symfonyfosrestbundle

How to expose a property of related object in serializer configuration in Symfony 2?


I use FOSRestBundle with JMSSerializerBundle in my web service. Here is a function in my action controller that returns a list of roles. I don't know how to return a "parent_id" field in this list.

<?php

use FOS\RestBundle\Controller\FOSRestController;

class RoleController extends FOSRestController
{
    ...
    /**
     * List all roles.
     *
     * @Annotations\View()
     *
     * @return array
     */
    public function getRolesAction()
    {
        $roles = $this->repository->findRoles();
        $view = $this->view($roles, 200);
        return $this->handleView($view);
    }
    ...
}

Here is my role entity. It has properties: id, name and parent. Parent is a role.

<?php

namespace AppBundle\Entity;

use Doctrine\ORM\Mapping as ORM;

/**
 * Role
 *
 * @ORM\Table()
 * @ORM\Entity(repositoryClass="AppBundle\Entity\RoleRepository")
 */
class Role
{
    /**
     * @var integer
     *
     * @ORM\Column(name="id", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    private $id;

    /**
     * @ORM\ManyToOne(targetEntity="Role")
     * @ORM\JoinColumn(name="parent_id", referencedColumnName="id")
     */
    private $parent;

    /**
     * @var string
     *
     * @ORM\Column(name="name", type="string", length=255)
     */
    private $name;

    // + getters and setters
    ...
}

Here is my serializer config file:

AppBundle\Entity\Role:
    exclusion_policy: ALL
    properties:
        id:
            expose: true
            type: integer
            xml_attribute: true
        name:
            expose: true
            type: string

Now getRolesAction in action controller will output JSON with id and name properties. How to add parent_id property to the serializer output?


Solution

  • You could use something like:

    /**
     * @Serializer\VirtualProperty
     * @Serializer\Type("integer")
     * @Serializer\SerializedName("parent_id")
     *
     * @return integer
     */
    public function getParentId()
    {
        return $this->parent->getId();
    }
    

    I can't tell you how to transfer the annotation in your config (probably YAML) format, but you'll be able to do that.

    IMPORTANT

    This only works for serialization - so don't expect this attribute to be deserialized later!!

    Alternative:

    If you only want to achieve the result you were asking for you could add this to your attribute:

    /** 
     * @Accessor(getter="getParentId",setter="setParent") */
     * @Serializer\Type("integer")
     * @Serializer\SerializedName("parent_id")
     */
    private $parent;
    

    and additionally another getter:

    /**
     *
     * @return integer
     */
    public function getParentId()
    {
        return $this->parent->getId();
    }
    

    With the accessor you tell JMS from which getter to get the result to serialize while still being able to use the setter for deserialization.