Изменение поведения Symfony с помощью действий AJAX

Предполагая, что у меня есть приложение, использующее множество запросов AJAX.

Есть ли способ редактировать поведение Symfony и автоматически вызывать indexAjaxAction вместо indexAction когда мой запрос выполнен AJAX?

Я уже знаю, что могу проверить, является ли запрос Ajax методом Request::isXmlHttpRequest() но я хочу, чтобы он был аутоматичным ( т.е. без тестирования в каждом контроллере).

Уже делает сервис / пакет?

Пример :

 <?php use Symfony\Bundle\FrameworkBundle\Controller\Controller; class FooController extends Controller { public function indexAction($vars) { $request = $this->getRequest(); if($request->isXmlHttpRequest()) { return $this->indexAjaxAction($vars); } // Do Stuff } public function indexAjaxAction($vars){ /* Do AJAX stuff */ } } 

становится

 <?php use Symfony\Bundle\FrameworkBundle\Controller\Controller; class FooController extends Controller { public function indexAction($vars) { } public function indexAjaxAction($vars) { } // Other functions } 

Solutions Collecting From Web of "Изменение поведения Symfony с помощью действий AJAX"

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

Обратите внимание, что я, возможно, ошибаюсь в своих мыслях здесь, и он не проверен.

Класс resolver контроллера имеет id controller_resolver.class который вы можете перезаписать с помощью своего настраиваемого в своей конфигурации, используя

В вашем app/config/config.yml

 .. config stuff .. parameters: controller_resolver.class: Acme\SomeBundle\Controller\ControllerResolver 

А затем в новом ControllerResolver

 namespace Acme\SomeBundle\Controller; use Symfony\Bundle\FrameworkBundle\Controller\ControllerResolver as BaseControllerResolver; class ControllerResolver extends BaseControllerResolver { /** * {@inheritdoc */ public function getArguments(Request $request, $controller) { if (is_array($controller) && $request->isXmlHttpRequest()) { $action = preg_replace( '/^(.*?)Action$/', '$1AjaxAction', $controller[1] ); try { $r = new \ReflectionMethod($controller[0], $action); return $this->doGetArguments( $request, $controller, $r->getParameters() ); } catch( \Exception $e) { // Do nothing } } return parent::getArguments($request, $controller); } } 

Этот класс просто расширяет текущий контроллер и пытается использовать youractionAjaxAction если он существует в контроллере, а затем возвращается к обычным распознавателям, если он получает ошибку (метод не найден);

В качестве альтернативы вы можете просто использовать …

 if (is_array($controller) && $request->isXmlHttpRequest()) { $controller[1] = preg_replace( '/^(?P<action>.*?)Action$/', '$1AjaxAction', $controller[1] ); } return parent::getArguments($request, $controller); 

.., который просто обновил вызываемое действие, а затем отправил его регулярному резольверу без отклонений, что означает, что для каждого действия, которое можно было бы вызвать с помощью XmlHttpRequest , потребуется соответствующий AjaxAction.

Вы можете посмотреть в FOSRestBundle для Symfony, это может быть очень полезно, если у вас есть 1 действие, которое может возвращать данные json или визуализированный html-шаблон в зависимости от метода запроса