如何在Symfony2控制器中获取操作名称?

10

有没有一种方法可以在Symfony2控制器中获取操作名称?

public function createAction(Request $request, $title) {

    // Expected result: create
    $name = $this->getActionName();

}
5个回答

22

使用:

$request->attributes->get('_controller');
// will get yourBundle\Controller\yourController::CreateAction

$params = explode('::',$request->attributes->get('_controller'));
// $params[1] = 'createAction';

$actionName = substr($params[1],0,-6);
// $actionName = 'create';

这也是错误的。动作方法不需要被称为“somethingAction”。可以通过在名称上添加检查来修复此问题,以确定是否以“action”结尾。 - Touki
@Touki,正如我在我的回答中提到的评论中所述,这个问题是一个Symfony2问题(见标签)。考虑阅读关于控制器命名约定的内容:http://symfony.com/doc/current/book/controller.html#a-simple-controller - Gottlieb Notschnabel
2
此外,一个操作可能在其函数参数声明中没有请求占位符,那么变量 $request 将不可访问。 - xsubira
如何获取控制器内的所有操作? - Braian Mellor

3
我在这里找到了这个代码片段(链接):
$matches    = array();
$controller = $this->getRequest()->attributes->get('_controller');
preg_match('/(.*)\\\(.*)Bundle\\\Controller\\\(.*)Controller::(.*)Action/', $controller, $matches);

这似乎是一种很有前途的方法。但这个正则表达式实际上并不起作用。但使用strstr()获取操作名称不会很难。有效!

并返回(查看示例

Array
(
    [0] => Acme\MyBundle\Controller\MyController::myAction
    [1] => Acme
    [2] => My
    [3] => My
    [4] => my
)

如果输入的是 Acme\MyBundle\Controller\MyController::myAction

补充上一句话:看看 @leo 的回答 :) - Gottlieb Notschnabel
我不明白你的意思。我想对当前选择的操作名称(logging)进行一些操作。是的,这应该通过监听器或服务来完成。但我不明白你为什么认为这是错误的?你能具体说明吗? - Gottlieb Notschnabel
如果控制器是 Acme\FooBundle\Controller\Foo::getBar,那么你的正则表达式将无法匹配。 - Touki
1
我坚持认为这并不是过于局限,因为它基于Symfony2的命名约定! - Gottlieb Notschnabel
1
我认为它是有效的,正则表达式只需要根据您正在使用的项目命名约定进行调整。如果您并未在所有控制器中使用Action,请从正则表达式中删除它。 - COil
显示剩余4条评论

1
现在,我正在使用这个与Symfony 2.8(和Symfony3)一起使用:
<?php

namespace Company\Bundle\AppBundle\Component\HttpFoundation;

use Symfony\Component\HttpFoundation\Request as BaseRequest;

/**
 * Request shortcuts.
 */
class Request extends BaseRequest
{
    /**
     * Extract the action name.
     *
     * @return string
     */
    public function getActionName()
    {
        $action = $this->get('_controller');
        $action = explode('::', $action);

        // use this line if you want to remove the trailing "Action" string
        //return isset($action[1]) ? preg_replace('/Action$/', '', $action[1]) : false;

        return $action[1];
    }

    /**
     * Extract the controller name (only for the master request).
     *
     * @return string
     */
    public function getControllerName()
    {
        $controller = $this->get('_controller');
        $controller = explode('::', $controller);
        $controller = explode('\\', $controller[0]);

        // use this line if you want to remove the trailing "Controller" string
        //return isset($controller[4]) ? preg_replace('/Controller$/', '', $controller[4]) : false;

        return isset($controller[4]) ? $controller[4] : false;
    }
}

要使用这个自定义请求类,您必须在您的web/app*.php控制器中“使用”它:
use Company\Bundle\AppBundle\Component\HttpFoundation\Request;
// ...
$request = Request::createFromGlobals();
// ...

然后在你的控制器中:
class AppController extends Controller
{
    /**
     * @Route("/", name="home_page")
     * @Template("")
     *
     * @return array
     */
    public function homePageAction(Request $request)
    {
        $controllerName = $request->getControllerName();
        $actionName = $request->getActionName();

        dump($controllerName, $actionName); die();

        // ...
    }

将输出:
AppController.php on line 27:
"AppController"
AppController.php on line 27:
"homePageAction"

您还可以通过RequestStack服务访问这些函数:

class MyService
{
    /**
     * @param RequestStack $requestStack
     */
    public function __construct(RequestStack $requestStack)
    {
        $this->requestStack = $requestStack;
    }

    public function myService()
    {
        $this->controllerName = $this->requestStack->getMasterRequest()->getControllerName();
        $this->actionName = $this->requestStack->getMasterRequest()->getActionName();

        // ...
    }

如何获取控制器内的所有操作? - Braian Mellor
请提出一个新问题。 - COil

1
如果您使用“控制器作为服务”模式,则模式不同: $request->attributes->get('_controller');将返回“service_id:createAction”
两种模式的可能解决方案:
$controller = $request->attributes->get('_controller');
$controller = str_replace('::', ':', $controller);
list($controller, $action) = explode(':', $controller);

0
在所有版本的Symfony中,无需$request或容器、服务或其他任何东西...,直接在您的方法中实现。
public function myMethod(){
   $methodName = __METHOD__;
   return $methodName;
}

// return App\Controller\DefaultController::myMethod

public function mySecondMethod(){
   $methodName = explode('::', __METHOD__);
   return $methodName[1];
}

// return mySecondMethod

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接