symfony2 вызов действия контроллера в расширении прута без обслуживания
Я программирую систему, которая имеет следующие функциональные возможности: обычные пользователи (без программистов и администраторов) могут создавать контент, в который они могут вставлять "заполнители". Эти заполнители будут заменены различными типами контента (например, шестнадцатеричный цветовой код, ползунок, изображение,...) при визуализации страницы. Замена заполнителей немного сложна и имеет некоторые дополнительные функции (например, определение значений по умолчанию, замена заполнителей содержимым на правильном языке,...). Из-за этого я создал расширение ветки с "заполнителем-фильтром". Эта функция должна получить правильный контент для замены заполнителя и обработки дополнительной функциональности. Поскольку типы содержимого настолько различны, есть некоторые - пусть это называется "плагины" - для каждого типа содержимого, который содержит логику для отображения содержимого в контроллере.
Теперь моя проблема:
Контроллер-действия плагинов возвращают визуализированный контент. Поскольку я заменяю заполнитель содержимым в расширении ветки, мне нужен способ вызова действия контроллера в этом расширении ветки.
Мои мысли до сих пор:
Я знаю, что могу вызывать действие контроллера в шаблоне таким образом (источник: http://symfony.com/doc/current/book/templating.html):
{{ render(controller(
'AppBundle:Article:recentArticles',
{ 'max': 3 }
)) }}
Так что, кажется, нет проблем с вызовом действия контроллера в ветке. Но мне нужен этот вызов функции в расширении ветки.
Я также знаю, что могу вызвать действие контроллера, когда я реализую контроллер как сервис. Но я не могу определить все контроллеры плагинов как сервисы, потому что плагины включены в систему динамически. Было бы "трудно" обрабатывать сервисы динамически при установке нового плагина (я думаю, что мне нужно отредактировать service.yml с помощью скрипта - или я ошибаюсь?). Вот почему я не могу использовать контроллер в качестве службы. - Но я открыт для других решений, когда вы можете сказать мне, как динамически реализовывать сервисы.
Я уже пробовал объединить решения этих двух страниц: http://symfony.com/doc/current/book/templating.html
echo $view['actions']->render(
new \Symfony\Component\HttpKernel\Controller\ControllerReference(
'AppBundle:Article:recentArticles',
array('max' => 3)
)
)
и https://www.robinvdvleuten.nl/blog/rendering-templates-in-a-twig-extension/
Теперь у меня есть доступ к Twig_Environment в моем заполнителе-фильтре в моем расширении ветки, но следующий код не работает:
$twig->render( new \Symfony\Component\HttpKernel\Controller\ControllerReference(
'Extensions'.$namespace.'Bundle:Index:getContent',
array('content'=>$contentObject)
), array() );
Я получаю сообщение об ошибке, что ControllerReference не может быть преобразован в строку (что имеет смысл, потому что ControllerReference является объектом...).
Так есть ли способ вызвать действие контроллера в расширении прута, не определяя контроллер как службу? Или я должен переосмыслить все решение?
2 ответа
После нескольких часов "размышлений о проблеме" я нашел простой ответ на главный вопрос. Когда я включаю Twig_environment в свою функцию фильтра (см. https://www.robinvdvleuten.nl/blog/rendering-templates-in-a-twig-extension/), я получаю доступ к функции render()- twig. Функция работает с шаблонами и строками. Таким образом, самый простой способ вызвать действие контроллера в расширении ветки без сервисов - это использовать обычный синтаксис twig-template:
// $twig is the Twig_Environment in my filter-function
$myRenderedContent = $twig->render(
"{{ render(controller( 'Extensions".$namespace."Bundle:Index:getContent', { 'content': content })) }}",
array('content'=>$contentObject)
);
Дополнительные мысли:
Как вы можете видеть в http://symfony.com/doc/current/book/templating.html вызов контроллера, подобный этому, кажется вполне приемлемым в Symfony. Так что я думаю, что также можно использовать эту функцию в расширении ветки (поскольку расширение ветки определяет дополнительные вспомогательные функции для рендеринга шаблона, и это то, что я хочу сделать с моей функцией фильтра, чтобы заменить специальные заполнители специальными содержание).
Может быть, это не лучшая практика - не включать мои плагин-контроллеры в качестве сервисов, но я не вижу недостатка в обработке плагин-контроллеров, как это до сих пор - когда вы знаете один: пожалуйста, скажите мне, потому что я открыт научиться "как сделать лучше";-)
Возможно, вы могли бы определить ViewListener и заставить ваш контроллер возвращать нужный вам html вместо ответа, который возвращается $this->render на контроллере.
Вам нужно будет использовать $this->renderView на контроллере и вернуть результат вашему расширению.
Я искренне чувствую, что вся система, настроенная таким образом, была бы очень хакерской и трудной для поддержания в долгосрочной перспективе, поэтому я бы рекомендовал переосмыслить ее