如何在Symfony2中将Request传递给Controller构造函数?

时间:2016-12-19 16:52:05

标签: symfony

我想将Request对象传递给控制器​​构造函数,如下所示:

public function __construct(Request $request){
        $this->startGameSession($request);
}

但是我收到了一个错误:

Catchable Fatal Error: Argument 1 passed to MyController::__construct() must be an instance of Symfony\Component\HttpFoundation\Request, none given...

同样适用于动作,但不适用于__construct。

4 个答案:

答案 0 :(得分:4)

要使用request中的__constructor实例,您需要将控制器定义为服务,而是注入request_stack服务(Ref.)。

  

控制器可以像任何其他类一样定义为服务。

namespace AppBundle\Controller;

use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\RequestStack;

class ServiceController extends Controller
{
    public function __construct(RequestStack $requestStack)
    {
        //do something with $requestStack->getCurrentRequest();
    }
}

然后你可以将它定义为一个服务如下(因为Symfony 3.3这可能不是必要的,因为自动装配):

# app/config/services.yml
services:
    service_controller:
        class: AppBundle\Controller\ServiceController
        arguments: ['@request_stack']

您还可以在定义路由_controller值时使用相同的表示法路由到服务。要引用定义为服务的控制器,请使用单个冒号(:)表示法。:

# app/config/routing.yml
index:
    path: /index
    defaults: { _controller: service_controller:indexAction }

就是这样!

答案 1 :(得分:2)

在Symfony控制器注册为服务的最新版本(> 3.4 - 不确定自何时起)。 https://symfony.com/doc/current/controller/service.html

只需将 RequestStack $ requestStack 作为参数传递给构造函数。

namespace AppBundle\Controller;

use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\RequestStack;

class MyController extends Controller
{
    public function __construct(RequestStack $requestStack)
    {
        $request = $requestStack->getCurrentRequest();
        //do something with the $request

    }
}

答案 2 :(得分:0)

你添加了:

use Symfony\Component\HttpFoundation\Request;

到您的文件顶部?

答案 3 :(得分:0)

当Symfony内核处理请求时,它正在尝试从请求中解析控制器。

namespace Symfony\Component\HttpKernel\Controller\ControllerResolver;

...

public function getController(Request $request)
{
    if (!$controller = $request->attributes->get('_controller')) {
        if (null !== $this->logger) {
            $this->logger->warning('Unable to look for the controller as the "_controller" parameter is missing.');
        }

        return false;
    }

    if (is_array($controller)) {
        return $controller;
    }

    if (is_object($controller)) {
        if (method_exists($controller, '__invoke')) {
            return $controller;
        }

        throw new \InvalidArgumentException(sprintf('Controller "%s" for URI "%s" is not callable.', get_class($controller), $request->getPathInfo()));
    }

    if (false === strpos($controller, ':')) {
        if (method_exists($controller, '__invoke')) {
            return $this->instantiateController($controller);
        } elseif (function_exists($controller)) {
            return $controller;
        }
    }

    $callable = $this->createController($controller);

    if (!is_callable($callable)) {
        throw new \InvalidArgumentException(sprintf('The controller for URI "%s" is not callable. %s', $request->getPathInfo(), $this->getControllerError($callable)));
    }

    return $callable;
}

控制器可以是:

  • 数组callables(对象/方法或类/静态方法组合)。
  • Invokable对象(具有魔术方法__invoke()的对象,如匿名对象) 函数,是\Closure)的一个实例。
  • 可调用对象的类。
  • 常规功能。
  • 作为字符串提供的任何其他控制器应采用class::methodBundleName:ControllerName:actionNameservice_id:methodName模式。

方法getController()返回控制器后,将从控制器生成响应并传递参数。

因此,您无法直接访问控制器构造,因为Symfony正在从Request对象创建控制器。