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

image

Я думаю, для многих не секрет, что компонент 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

© Habrahabr.ru