FOSRestBundle: частичный ответ в функции атрибутов, запрашиваемых в запросе

Я нашел много вопросов о частичном ответе API с помощью FOSRest, и все ответы основаны на опциях сериализатора JMS (исключить, включить, группы и т. Д.). Это работает нормально, но я пытаюсь добиться чего-то менее «статичного».

Допустим, у меня есть пользователь со следующими атрибутами: id username firstname lastname age sex

Я получаю этого пользователя с конечной точки GET /users/{id} и следующий метод:

/**
* @View
*
* GET /users/{id}
* @param integer $user (uses ParamConverter)
*/
public function getUserAction(User $user) {
return $user;
}

Метод возвращает пользователя со всеми его атрибутами.

Теперь я хочу разрешить что-то подобное: GET /users/{id}?attributes=id,username,sex

Я пропустил функциональность FOSRestBUndle, JMSserializer или SensioFrameworkExtraBundle, чтобы достичь этого автоматически? Аннотация, метод, ключевое слово в запросе или что-то еще?

Иначе, как лучше всего это сделать?

Я думал сделать что-то подобное:

/**
* @View
* @QueryParam(name="attributes")
*
* GET /users/{id}
*
* @param integer $user (uses ParamConverter)
*/
public function getUserAction(User $user, $attributes) {
$groups = $attributes ? explode(",", $attributes) : array("Default");

$view = $this->view($user, 200)
->setSerializationContext(SerializationContext::create()->setGroups($groups));

return $this->handleView($view);
}

И создайте группу для каждого атрибута:

use JMS\Serializer\Annotation\Groups;

class User {

/** @Groups({"id"}) */
protected $id;

/** @Groups({"username"}) */
protected $username;

/** @Groups({"firstname"}) */
protected $firstname;

//etc
}

5

Решение

Вы можете сделать это так через группы, как вы показали. Может быть, немного более элегантным решением было бы реализовать свой собственный ExclusionStrategy. @Groups и другие тоже являются реализациями ExclusionStrategyInterface.

Итак, скажем, вы назвали свою стратегию SelectFieldsStrategy. Как только вы реализуете его, вы можете очень легко добавить его в контекст сериализации:

$context = new SerializationContext();
$context->addExclusionStrategy(new SelectFieldsStrategy(['id', 'name', 'someotherfield']));
3

Другие решения

Моя реализация основана на Игорь ответ:

ExlusionStrategy:

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

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

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

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

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

if (in_array($property->name, $this->fields)) {
return false;
}

return true;
}
}

контроллер:

/**
* @View
* @QueryParam(name="fields")
*
* GET /users/{id}
*
* @param integer $user (uses ParamConverter)
*/
public function getUserAction(User $user, $fields) {
$context = new SerializationContext();
$context->addExclusionStrategy(new FieldsExclusionStrategy($fields ? explode(',', $fields) : array()));

return $this->handleView($this->view($user)->setSerializationContext($context));
}

Конечная точка:

GET /users/{id}?fields=id,username,sex
4

По вопросам рекламы [email protected]