Symfony: обробка запитів в API

image

Я думаю, для багатьох не секрет, що компонент Form погано підходить для роботи в API,
кожен винаходить свій велосипед на заміну, одним з таких велосипедів я вирішив поділитися. На звання «кращого рішення» я не претендую, але якщо моє рішення комусь буде корисно, або я отримаю нові знання – буде дуже здорово.

У нашій API кожен запит обробляється з допомогою моделі, не важливо це сутність доктрини або просто клас. Тому рішення побудовано навколо анотацій всередині цих моделей.

Модель може виглядати приблизно так:

Лістинг моделі
<?php
namespace Common\Model;

Common use\Constraint as AppAssert;
use Symfony\Component\Validator\Constraints as Assert;
use Troytft\DataMapperBundle\Annotation\DataMapper;

class PostsFilter
{
/**
* @DataMapper(type="string")
*/
protected $query;

/**
* @DataMapper(type="entity", options={"class": "CommonBundle:City"})
* @Assert\NotBlank
*/
protected $city;

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

/**
* @param mixed $value
*/
public function setCity($value)
{
$this->city = $value;

return $this;
}

/**
* @return string
*/
public function getQuery()
{
return $this->query;
}

/**
* @param string $value
*/
public function setQuery($value)
{
$this->query = $value;

return $this;
}
}


Анотація приймає наступні параметри:
name (не обов'язковий параметр, ім'я полі в запиті)
type (не обов'язковий параметр, тип поля, можливі значення: string, integer, float, boolean, timestamp, array, entity, array_of_entity)
groups (не обов'язковий параметр scope запиту, потрібно, якщо одна і та ж модель використовується в різних місцях, але з різним набором полів)

А тепер те, як це виглядає в контролері:

/** @var Request $request */
$request = $this- > get('request');
$data = $request->getRealMethod() == 'GET' ? $request->query->all() : $request->request->all();

/** @var DataMapperManager $manager */
$manager = $this- > get('data_mapper.manager');

$model = $manager
->setGroups($groups)
->setValidationGroups($validationGroups)
->setIsClearMissing($clearMissing)
->setIsValidate(true)
->handle($model, $data);


Менеджер сам смаппит всі дані на модель, запустить валідацію і якщо вона не пройде – викине виняток.

Якщо ж говорити про реальне використання, то весь код контролера виноситься в базовий контролер, і всередині реальних екшенів коду стає вкрай мало:

public function createAction()
{
$user = $this->getUser();
$entity = $this->save($this->handleRequest(new Common\Entity\Blog\Post($this->getUser ())));

$this->getNotificationManager()->notifyModerators($entity);

return $entity;
}


Код проекту:
— github: github.com/Troytft/data-mapper
— packagist: packagist.org/packages/troytft/data-mapper-bundle

Джерело: Хабрахабр

0 коментарів

Тільки зареєстровані та авторизовані користувачі можуть залишати коментарі.