使用AJAX操作编辑Symfony行为


Edit Symfony behavior with AJAX actions

假设我有一个使用大量AJAX请求的应用程序。

是否有一种方法来编辑Symfony行为,并自动调用indexAjaxAction而不是indexAction时,我的请求是AJAX ?

我已经知道,我可以测试如果一个请求是Ajax与Request::isXmlHttpRequest()方法,但我希望它是自动的( I。e无需在每个controllerAction中测试)。

一个服务/bundle已经成功了吗?

例子:

<?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进程中当前的控制器解析器。

请注意,我的想法可能是错误的,这是未经测试的。

控制器解析器类的id为controller_resolver.class,您可以使用

在配置中使用自定义的id覆盖它。

在你的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。

你可能想看看Symfony的FOSRestBundle,它可以是非常有用的,如果你有一个动作,可以返回json数据或呈现html模板取决于请求方法