Symfony 4: как получить избирателей, которые проголосовали как должное?
Как я могу получить избирателей, которые проголосовали за "предоставленное", внутри подписчика события? Есть ли какой-нибудь сервис, который я могу получить и использовать?
Мой вариант использования. Мое приложение имеет двух избирателей: основного избирателя и избирателя-администратора. Я хочу показать дополнительное флэш-сообщение, когда доступ запрещен основным избирателем, но разрешен избирателем-администратором. Я могу решить эту проблему двумя различными решениями: отправив событие внутри избирателя администратора или установив flash msg внутри избирателя - но я хочу избежать этого, потому что мне нужно быть уверенным, что ТОЛЬКО один избиратель проголосовал за доступ.
1 ответ
Итак, я начну с решений, которые ответят на вопрос, который вы задали. Я закончу с решением (ИМХО) основной проблемы.
Чрезвычайно тривиальное решение:
Объедините обоих избирателей в один, заменив их обоих. Установка флеш-сообщения, если ваше условие выполнено, является обязанностью этого объединенного избирателя, но это тривиально, поскольку у вас есть "результаты" обоих избирателей...
Чуть более красноречиво:
Создайте CombinedVoter, заменив оба. CombinedVoter будет принимать обоих избирателей в качестве зависимостей и направлять им запросы на голосование и возвращать / разыгрывать соответствующую комбинацию из них (по сути, AccessDecisionManager, замаскированный под избирателя). Очевидно, избиратель установит флэш-сообщение, когда ваше условие будет выполнено.
Чуть более бесполезно:
Создайте CombinedVoter, ничего не заменяя, но по-прежнему получая обоих избирателей в качестве зависимостей, направляйте им запросы на голосование и возвращайте ABSTAIN во всех случаях. Очевидно, избиратель установит флэш-сообщение, когда ваше условие будет выполнено.
Чуть более перегружен:
Добавьте EventDispatcher обоим избирателям и отправьте события голосования. Позвольте слушателю прослушать эти события и либо сработать, когда он получит второе (грязный af), либо снова сработает на событии ядра, чтобы установить флэш-сообщение, когда ваше условие выполнено.
Чуть менее перегружен:
Добавьте сервис, который также является EventListener, который прослушивает одно и то же событие ядра для установки флэш-сообщения, но не прослушивает события голосования, вместо этого внедряет этот сервис в обоих избирателей и устанавливает результат голосования непосредственно в этом сервисе. с помощью setAdminVote()
/ setMainVote()
или что угодно.
Основная проблема:
Семантически, ваши избиратели не должны заботиться о флеш-сообщениях и том, что проголосовали другие избиратели. Это не их цель и не их ответственность. Чтобы добавить это к их функции, ИМХО ошибочно, это не то место и время! (Семантика!)
Вместо этого, поскольку в любом случае это, вероятно, специальное сообщение, почему бы не добавить его в базовый шаблон (безусловно, есть способы проверить, является ли кто-то администратором, но не разрешен "основным избирателем", например, используя is_granted
в шаблоне или app.user.roles
напрямую (при необходимости). Вы также можете написать небольшое расширение веточки, которое добавляет эту функцию и каким-то образом использует обоих избирателей.
Почему я предлагаю поместить эту логику в шаблон: потому что это проблема отображения. Вы хотите, чтобы что-то отображалось, поэтому оно должно быть размещено в части отображения вашего приложения. Кроме того, существует множество крайних случаев, которые вы, вероятно, игнорируете, не знаете или прикладываете усилия, чтобы избежать: Отправка формы на странице, которая вызовет флэш-сообщение, вероятно, приведет к добавлению флэш-сообщения в POST (что, если сделано чисто запускает перенаправление на страницу с GET) И на следующем GET, по существу добавляя два флеш-сообщения. Теперь вы не можете добавить флэш-сообщение к запросам POST, но тогда недействительные формы POSTED будут без флэш-сообщения (потому что не будет GET). Это разум е ***. Я действительно советовал бы против этого.
Отображение - это работа внешнего интерфейса, добавьте несколько помощников в службы / расширения. Пусть избиратели сохраняют свою единственную ответственность (которая, конечно, НЕ добавляет флеш-сообщения). возможно, расширьте ваш базовый шаблон, чтобы он функционировал как "страницы, использующие расширенный базовый шаблон, должны отображать сообщение", а затем используйте его на страницах, на которых вы хотите показать сообщение.
Действительно, делай это чисто; о)
Приложение:
Флэш-сообщения, как правило, обеспечивают обратную связь с пользователем о действиях, которые он недавно совершил. Например, пользователь удалил запись в блоге. Затем в сообщении должно появиться сообщение "блог был удален" (может содержать больше информации ^^).
А полезность сессионной флеш-карты заключается в том, что флеш-сообщения будут храниться там до тех пор, пока они не будут извлечены. Это удобно для обратной связи, потому что обычно она отображается при следующей визуализации страницы.
Есть много случаев, когда с этим было бы трудно справиться иначе. Что делать, если вы загружаете только фрагменты своей страницы (возможно, Ajax-обновления), не хотите, чтобы ваше флеш-сообщение было там, также не удалено. Что делать, если вы разместили форму и успешно перенаправлены на какую-то совершенно не связанную страницу. Должна ли эта страница знать что-либо о происхождении пользователя? Желательно нет (разделение интересов). Флэш-сообщения не волнуют (единственная ответственность). Разработчик решает, где могут отображаться флеш-сообщения (обычно при "полном рендеринге страницы" или при специальном доступе).
Они тоже не серебряная пуля. Если у вас открыто несколько вкладок браузера, они могут запутаться до чертиков (поскольку могут отображаться флеш-сообщения, созданные с другой вкладки). Однако если вашей веб-странице требуется несколько вкладок в браузере, у вас также есть некоторые другие проблемы. Тем не менее, я чувствую, что принятие случайного "блуждающего флеш-сообщения" - это хорошо.