
Примечание
Использование Symfony2 и AngularJs в связке является хорошей идеей, но есть одна проблема — решение из коробки обладает проблемой в коммуникации. В этом посте будет рассказано о том, как автоматически декодировать JSON-запросы и использовать полученные данные при помощи Request Symfony используя библиотеку symfony-json-request-transformer (на самом деле всего-то один класс).
Идея
$http-сервис AngularJs автоматически отправляет данные с заголовкомContent-Type: application/json
в POST запросе, а Symfony в свою очередь ожидает application/x-www-form-urlencoded
.Для примера, отправим из нашего angular-приложения простой JSON-объект:
{
"name": "John"
}
Теперь в контроллере получим эти данные:
public function postAction(Request $request)
{
$data = json_decode($request->getContent(), true);
echo $data['name']; // John
}
Довольно просто, верно? Но, к сожалению, мы не можем использовать ParameterBag интерфейс в объекте Request в данном случае.
Если
name
опционален и имеет значение по-умолчанию, хотелось бы получать данные вот так:$name = $request->request->get('name', 'Ivan');
К счастью, используя метод replace мы можем заменить данные в ParameterBag на наш декодированный JSON.
public function postAction(Request $request)
{
$data = json_decode($request->getContent(), true);
$request->request->replace($data);
echo $request->request->get('name', 'Ivan'); // John
}
Отлично, работает так, как нам хотелось. Но, ведь это только один контроллер…
Реализация

kernel.event_listener
, он:- Проверит запрос на наличие заголовка
Content-Type: application/json
- Если это так — декодирует его
- Заполнит объект
Request::$request
- Вернет код ошибки
HTTP 400 Bad Request
, если что-то пошло не так
Можете увидеть полный код на Github.
Зарегистрировать обработчик события очень просто, просто определив новый сервис:
<service id="kernel.event_listener.json_request_transformer" class="Qandidate\Common\Symfony\HttpKernel\EventListener\JsonRequestTransformerListener">
<tag name="kernel.event_listener" event="kernel.request" method="onKernelRequest" priority="100" />
</service>