如何使用Symfony方法Action排除“Action”字样

时间:2016-03-28 15:24:27

标签: symfony routing

我目前正在将一个现有的应用程序迁移到Symfony2,它有大约100个控制器,每个控制器中有大约8个动作。所有当前的操作都命名如下:

public function index(){}

然而,Symfony的默认命名约定是indexAction()。 是否可以保留我当前的所有操作并告诉Symfony在方法名称后面没有“Action”字样的情况下使用它? 谢谢。

2 个答案:

答案 0 :(得分:2)

是的,这是可能的。您应该能够正常定义路由,但您需要更改内核找到控制器的方式。执行此操作的最佳方法是替换/装饰/扩展服务' controller_name_converter'。这是一项私人服务,并被注入' controller_resolver'服务。

您要替换的类的源代码位于Symfony \ Bundle \ FrameworkBundle \ Controller \ ControllerNameParser'。

基本上,代码就像这样运行。 '捆绑:控制器:动作'您在创建路由时指定的内容保存在缓存中。当一个路由匹配时,该字符串将被返回给内核,而内核又会调用' controller_resolver'它调用' controller_name_resolver'。该类将字符串转换为" namespace :: method"符号

查看decorating services以了解如何操作。

这是一个可以使用的未经测试的课程

class ActionlessNameParser
{
    protected $parser;

    public function __construct(ControllerNameParser $parser)
    {
        $this->parser = $parser;
    }

    public function parse($controller)
    {
        if (3 === count($parts = explode(':', $controller))) {
            list($bundle, $controller, $action) = $parts;
            $controller = str_replace('/', '\\', $controller);

            try {
                // this throws an exception if there is no such bundle
                $allBundles = $this->kernel->getBundle($bundle, false);
            } catch (\InvalidArgumentException $e) {
                return $this->parser->parse($controller);
            }

            foreach ($allBundles as $b) {
                $try = $b->getNamespace().'\\Controller\\'.$controller.'Controller';
                if (class_exists($try)) {
                    // You can also try testing if the action method exists.
                    return $try.'::'.$action;
                }
            }
        }

        return $this->parser->parse($controller);
    }

    public function build($controller)
    {
        return $this->parser->build($controller);
    }
}

并替换原始服务,如:

actionless_name_parser:
  public: false
  class: My\Namespace\ActionlessNameParser
  decorates: controller_name_converter
  arguments: ["@actionless_name_parser.inner"]

答案 1 :(得分:0)

显然,Action后缀用于区分映射到路由的内部方法和方法。 (根据这个question)。

确定的最佳方式是尝试。

// src/AppBundle/Controller/HelloController.php
namespace AppBundle\Controller;

use Symfony\Component\HttpFoundation\Response;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;

class HelloController
{
    /**
     * @Route("/hello/{name}", name="hello")
     */
    public function indexAction($name)
    {
        return new Response('<html><body>Hello '.$name.'!</body></html>');
    }
}

尝试从方法名称中删除Action,看看会发生什么。