donglankui1263 2014-07-10 08:57
浏览 48
已采纳

使用AJAX操作编辑Symfony行为

Assuming I have an application using a lot of AJAX requests.

Is there a way to edit Symfony behavior and autommatically call indexAjaxAction instead of indexAction when my request is AJAX made ?

I already know that I can test if a request is Ajax with the Request::isXmlHttpRequest() method but I want it to be autommatic (i.e without testing in each controllerAction).

Does a service/bundle already makes it ?

Example :

<?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 */ }
}

becomes

<?php 

use Symfony\Bundle\FrameworkBundle\Controller\Controller;

class FooController extends Controller
{
    public function indexAction($vars) { }
    public function indexAjaxAction($vars) { }

    // Other functions
}
  • 写回答

2条回答 默认 最新

  • doujiaochan7317 2014-07-10 10:00
    关注

    One way would be to use a slightly modified controller resolver that would be used instead of the current controller resolver in the regular KttpKernel::handleRaw process.

    Please note that I may be wrong in my thinking here and it is untested.

    The controller resolver class has the id controller_resolver.class which you could overwrite with your custom one in your config using

    In your app/config/config.yml...

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

    And then in your new 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);
        }
    }
    

    This class just extends the current controller resolver and will attempt to use the youractionAjaxAction if it exists in the controller and then falls back to the regular resolver if it gets an error (method not found);

    Alternatively you could just use...

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

    .. which would just update the called action and then send it through to the regular resolver with no fall back, meaning that every action that could be called using an XmlHttpRequest would require a corresponding AjaxAction.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(1条)

报告相同问题?

悬赏问题

  • ¥15 一道python难题
  • ¥15 用matlab 设计一个不动点迭代法求解非线性方程组的代码
  • ¥15 牛顿斯科特系数表表示
  • ¥15 arduino 步进电机
  • ¥20 程序进入HardFault_Handler
  • ¥15 oracle集群安装出bug
  • ¥15 关于#python#的问题:自动化测试
  • ¥20 问题请教!vue项目关于Nginx配置nonce安全策略的问题
  • ¥15 教务系统账号被盗号如何追溯设备
  • ¥20 delta降尺度方法,未来数据怎么降尺度