Kamil P
Kamil P

Reputation: 784

Symfony - FOSRestBundle - show selected fields

I'm trying to show only selected fields in my REST action in controller. I've found one solution - I can set groups in Entities/Models and select this group in annotation above action in my Controller.

But actually i don't want use groups, i want determine which fields i wanna expose.

I see one solution - I can create one group for every field in my Entities/Model. Like this:

class User
{
    /**
     * @var integer
     *
     * @Groups({"entity_user_id"})
     */
    protected $id;

    /**
     * @var string
     *
     * @Groups({"entity_user_firstName"})
     */
    protected $firstName;

    /**
     * @var string
     *
     * @Groups({"entity_user_lastName"})
     */
    protected $lastName;
}

And then i can list fields above controller action.

My questions are:

  1. Can I use better solution for this?

  2. Can I list all groups? Like I can list all routes or all services.

Upvotes: 2

Views: 1155

Answers (1)

nakashu
nakashu

Reputation: 1068

This is mainly about serialization not about fosrestbundle itself.

The right way would be to create your own fieldserialization strategy. This article got it down really nicely:

http://jolicode.com/blog/how-to-implement-your-own-fields-inclusion-rules-with-jms-serializer

It build a custom exclusion strategy as describeted here:

How do I create a custom exclusion strategy for JMS Serializer that allows me to make run-time decisions about whether to include a particular field?

Example code from first link for reference:

custom FieldExclusion strategy:

namespace Acme\Bundle\ApiBundle\Serializer\Exclusion;

use JMS\Serializer\Exclusion\ExclusionStrategyInterface;
use JMS\Serializer\Metadata\ClassMetadata;
use JMS\Serializer\Metadata\PropertyMetadata;
use JMS\Serializer\Context;

class FieldsListExclusionStrategy implements ExclusionStrategyInterface
{
    private $fields = array();

    public function __construct(array $fields)
    {
        $this->fields = $fields;
    }

    /**
     * {@inheritDoc}
     */
    public function shouldSkipClass(ClassMetadata $metadata, Context $navigatorContext)
    {
        return false;
    }

    /**
     * {@inheritDoc}
     */
    public function shouldSkipProperty(PropertyMetadata $property, Context $navigatorContext)
    {
        if (empty($this->fields)) {
            return false;
        }

        $name = $property->serializedName ?: $property->name;

        return !in_array($name, $this->fields);
    }
}

Interface

interface ExclusionStrategyInterface
{
    public function shouldSkipClass(ClassMetadata $metadata, Context $context);
    public function shouldSkipProperty(PropertyMetadata $property, Context $context);
}

usage

in controller or where you need it:

$context = new SerializationContext();
$fieldList = ['id', 'title']; // fields to return    
$context->addExclusionStrategy(
    new FieldsListExclusionStrategy($fieldList)
);

// serialization
$serializer->serialize(new Pony(), 'json', $context);

You should be also able to mix and match with groups eg. you can also set $content->setGroups(['myGroup']) together with the fieldExclusio

Upvotes: 1

Related Questions