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

от автора

image

Я думаю, для многих не секрет, что компонент Form плохо подходит для работы в API,
каждый изобретает свой велосипед на замену, одним из таких велосипедов я решил поделиться. На звание “лучшего решения” я не претендую, но если мое решение кому-нибудь окажется полезно, либо я получу новые знания – будет очень здорово.

В нашей API каждый запрос обрабатывается с помощью модели, не важно это сущность доктрины или просто класс. Поэтому решение построено вокруг аннотаций внутри этих моделей.

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

Листинг модели

<?php namespace Common\Model;  use Common\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

ссылка на оригинал статьи https://habrahabr.ru/post/281875/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *