Symfony: обработка запросов в API
Я думаю, для многих не секрет, что компонент Form плохо подходит для работы в API,
каждый изобретает свой велосипед на замену, одним из таких велосипедов я решил поделиться. На звание «лучшего решения» я не претендую, но если мое решение кому-нибудь окажется полезно, либо я получу новые знания — будет очень здорово.
В нашей API каждый запрос обрабатывается с помощью модели, не важно это сущность доктрины или просто класс. Поэтому решение построено вокруг аннотаций внутри этих моделей.
Модель может выглядеть примерно так:
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