Как запретить профилировщику Symfony доступ или выполнение слушателя

У моего пользователя есть свойство countTasks с соответствующим сеттером и геттером:

class User implements UserInterface, \Serializable
{
    /**
     * @var integer
     */
    private $countTasks;
}

Я хочу, чтобы это свойство всегда отображалось на панели навигации приложения (цифра "14" красного цвета):

панель навигации со свойством countTasks

Очевидно, что это свойство должно быть установлено для каждого контроллера. (На самом деле, только для всех, кто занимается рендерингом панели навигации, но здесь это не так). Таким образом, приложение должно подсчитывать задачи для текущего пользователя, вошедшего в систему, для каждого контроллера.

Я нашел соответствующую тему в поваренной книге Symfony: Как настроить до и после фильтров, и мне удалось это реализовать:

Acme\TestBundle\EventListener\UserListener.php:

namespace Acme\TestBundle\EventListener;
use Symfony\Component\HttpKernel\Event\FilterControllerEvent;

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

        if ( ! is_array($controller)) {
            return;
        }

        $securityContext = $controller[0]->get('security.context');

        // now count tasks, but only if a user logged-in
        if ($securityContext->isGranted('IS_AUTHENTICATED_REMEMBERED') or $securityContext->isGranted('IS_AUTHENTICATED_FULLY'))
        {
            $user = $securityContext->getToken()->getUser();

            // ...
            // countig tasks and setting $countTasks var
            // ...
            $user->setCountTasks($countTasks);
        }
    }
}

services.yml:

services:
    acme.user.before_controller:
        class: Acme\TestBundle\EventListener\UserListener
        tags:
            - { name: kernel.event_listener, event: kernel.controller, method: onKernelController }

Он работает так, как ожидалось, и я могу получить свойство в шаблоне Twig следующим образом:

{{ app.user.countTasks }}

В prod env он работает так, как ожидалось.
Однако в dev профайлер выдает UndefinedMethodException:

UndefinedMethodException: Попытка вызвать метод «get» для класса «Symfony\Bundle\WebProfilerBundle\Controller\ProfilerController» в ...\src\Acme\TestBundle\EventListener\UserListener.php, строка 18.

где строка 18 это:

$securityContext = $controller[0]->get('security.context');

В качестве быстрого патча я добавил дополнительную проверку (перед строкой 18), чтобы профилировщик не выполнял дальнейшую логику:

    if (is_a($controller[0], '\Symfony\Bundle\WebProfilerBundle\Controller\ProfilerController'))
    {
        return;
    }

    $securityContext = $controller[0]->get('security.context');

и это сделало трюк. Но боюсь, это не правильный путь. Я также боюсь потерять часть отладочной информации в профилировщике.

Прав ли я в своих опасениях? Можете ли вы указать мне лучший способ предотвратить выполнение этого прослушивателя профилировщиком? В конфиге как-то?


person Taz    schedule 18.08.2014    source источник


Ответы (2)


Даже в документации Symfony Как настроить фильтры до и после экземпляр условия оценивается в строке 29.

Я бы сказал, что если это делает док, вы вполне можете сделать это самостоятельно (если не указано иное, что не так).

person Noy    schedule 18.08.2014
comment
Спасибо, что указали мне в этом направлении @Noy - это помогло мне найти правильное решение (я опубликую его позже). Однако я не могу принять ваш ответ из-за ваших рассуждений - если документа недостаточно. Также меня волнует не то, как я это делаю (функция is_a()), а связь, которую вводит этот метод. - person Taz; 21.08.2014

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

В итоге я создал пустой интерфейс UserTasksAwareController:

namespace Acme\TestBundle\Controller;

interface UserTasksAwareController
{}

исправление этой проверки достоверности в UserListener.php:

if ( ! $controllers[0] instanceof UserTasksAwareController) {
    return;
}

и реализовать его в каждом другом контроллере, который имеет дело с отображением свойства countTasks, как этот:

class UserController extends Controller implements UserTasksAwareController

Итак, проблема, с которой я столкнулся, была еще одной, когда вы забыли запрограммировать интерфейс, а не реализацию.

person Taz    schedule 03.09.2014