Предполагая, что у меня есть приложение, использующее множество запросов 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 }
Один из способов – использовать слегка модифицированный контроллер, который будет использоваться вместо текущего контроллера в обычном процессе 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-шаблон в зависимости от метода запроса