Упростите процедуру вызова @Route в Symfony с помощью EventListener

У меня есть «стандартная процедура», которая мне нужна в КАЖДОМ маршруте, который я вызываю в Symfony.
Я в основном создаю короткий (относительно) уникальный номер, проверяю разрешение и регистрирую, что функция была вызвана.

Вот один пример:

**
* @Route("/_ajax/_saveNewClient", name="saveNewClient")
*/
public function saveNewClientAction(Request $request)
{

/* Create Unique TrackNumber */
$unique= $this->get('log')->createUnique();

/* Check Permission */
if (!$permission = $this->get('permission')->needsLevel(2, $unique)) {

/* Log Action */
$this->get('log')->writeLog('No Permission, 2 needed', __LINE__, 4);
return new JsonResponse(array(
'result' => 'error',
'message' => 'Insufficient Permission'
)
);
}

/* Log Action */
$this->get('log')->writeLog('called '.__FUNCTION__, __LINE__, 1, $unique);

return $this->render(':admin:index.html.twig', array());

}

Есть ли способ поместить все это в одну функцию где-нибудь?

writeLog вызывается также в других частях функций, поэтому я не хочу сочетать его с проверкой разрешений, хотя это, конечно, возможно.

При создании EventListener, я все еще должен вызывать его в каждой функции или возможно, чтобы он вызывался автоматически?

Любая подсказка приветствуется!

1

Решение

Вы могли бы попытаться сделать предварительный фильтр.

http://symfony.com/doc/current/cookbook/event_dispatcher/before_after_filters.html

Как настроить фильтры до и после

При разработке веб-приложений довольно часто требуется, чтобы некоторая логика выполнялась непосредственно перед или сразу после действий вашего контроллера, выступающих в качестве фильтров или ловушек.

Некоторые веб-фреймворки определяют методы, такие как preExecute () и postExecute (), но в Symfony такого нет. Хорошей новостью является то, что существует гораздо лучший способ вмешиваться в процесс Запрос -> Ответ с использованием компонента EventDispatcher.

Пример проверки токена

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

Итак, перед выполнением действия вашего контроллера вам необходимо проверить, ограничено ли действие или нет. Если он ограничен, вам необходимо проверить предоставленный токен.

Обратите внимание, что для простоты в этом рецепте токены будут определены в конфигурации, и не будут использоваться ни настройка базы данных, ни аутентификация через компонент безопасности.

Перед фильтрами с событием kernel.controller

Во-первых, сохраните некоторую базовую конфигурацию токена, используя config.yml и ключ параметров:

YAML

# app/config/config.yml
parameters:
tokens:
client1: pass1
client2: pass2

Контроллеры тегов должны быть проверены

Слушатель kernel.controller получает уведомление о каждом запросе непосредственно перед выполнением контроллера. Итак, во-первых, вам нужен какой-то способ определить, нуждается ли контроллер, соответствующий запросу, в проверке токена.

Простой и понятный способ — создать пустой интерфейс и заставить его реализовывать контроллеры:

namespace AppBundle\Controller;

interface TokenAuthenticatedController
{
// ...
}

Контроллер, который реализует этот интерфейс, выглядит просто так:

namespace AppBundle\Controller;

use AppBundle\Controller\TokenAuthenticatedController;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;

class FooController extends Controller implements TokenAuthenticatedController
{
// An action that needs authentication
public function barAction()
{
// ...
}
}

Создание прослушивателя событий

Затем вам нужно создать прослушиватель событий, который будет содержать логику, которую вы хотите выполнить перед вашими контроллерами. Если вы не знакомы со слушателями событий, вы можете узнать о них больше в разделе Как создать слушателей событий и подписчиков:

// src/AppBundle/EventListener/TokenListener.php
namespace AppBundle\EventListener;

use AppBundle\Controller\TokenAuthenticatedController;
use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
use Symfony\Component\HttpKernel\Event\FilterControllerEvent;

class TokenListener
{
private $tokens;

public function __construct($tokens)
{
$this->tokens = $tokens;
}

public function onKernelController(FilterControllerEvent $event)
{
$controller = $event->getController();

/*
* $controller passed can be either a class or a Closure.
* This is not usual in Symfony but it may happen.
* If it is a class, it comes in array format
*/
if (!is_array($controller)) {
return;
}

if ($controller[0] instanceof TokenAuthenticatedController) {
$token = $event->getRequest()->query->get('token');
if (!in_array($token, $this->tokens)) {
throw new AccessDeniedHttpException('This action needs a valid token!');
}
}
}
}

Регистрация слушателя

Наконец, зарегистрируйте ваш слушатель как службу и отметьте его как слушатель событий. Прослушивая kernel.controller, вы говорите Symfony, что хотите, чтобы ваш слушатель был вызван непосредственно перед выполнением любого контроллера.

YAML

# app/config/services.yml
services:
app.tokens.action_listener:
class: AppBundle\EventListener\TokenListener
arguments: ['%tokens%']
tags:
- { name: kernel.event_listener, event: kernel.controller, method: onKernelController }

В этой конфигурации ваш метод TokenListener onKernelController будет выполняться при каждом запросе. Если контроллер, который должен быть выполнен, реализует TokenAuthenticatedController, применяется аутентификация токена. Это позволяет вам иметь фильтр «до» на любом контроллере, который вы хотите.

0

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]