3

我正在将我的应用程序从 Symfony 2.8 迁移到 Symfony 3.3。

从我的控制器内部,我有这个:

public function indexAction()
{
    $email = new Email();

    $form = $this->createForm(GetStartedType::class, $email, [
        'action' => $this->generateUrl('get_started_end'),
        'method' => 'POST',
    ]);

    return [
        'form' => $form->createView(),
    ];
}

但我收到了这个例外:

在 null 上调用成员函数 get()

我的控制器扩展Symfony\Bundle\FrameworkBundle\Controller\Controller

/**
 * {@inheritdoc}
 */
class DefaultController extends Controller
{
...
}

所以我可以访问容器。

在 Symfony 的代码中放置一些转储,我看到容器设置正确:

namespace Symfony\Component\DependencyInjection;

/**
 * ContainerAware trait.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
trait ContainerAwareTrait
{
    /**
     * @var ContainerInterface
     */
    protected $container;

    /**
     * Sets the container.
     *
     * @param ContainerInterface|null $container A ContainerInterface instance or null
     */
    public function setContainer(ContainerInterface $container = null)
    {
        dump('Here in the ContainerAwareTrait');
        dump(null === $container);
        $this->container = $container;
    }
}

这转储

Here in the ContainerAwareTrait
false

因此自动装配运行良好并设置了容器。

但在ControllerTrait我有这个:

trait ControllerTrait
{
    /**
     * Generates a URL from the given parameters.
     *
     * @param string $route         The name of the route
     * @param mixed  $parameters    An array of parameters
     * @param int    $referenceType The type of reference (one of the constants in UrlGeneratorInterface)
     *
     * @return string The generated URL
     *
     * @see UrlGeneratorInterface
     */
    protected function generateUrl($route, $parameters = array(), $referenceType = UrlGeneratorInterface::ABSOLUTE_PATH)
    {
        dump('Here in the ControllerTrait');
        die(dump(null === $this->container));
        return $this->container->get('router')->generate($route, $parameters, $referenceType);
    }

    ...

这是转储:

Here in the ControllerTrait
true

所以这里containernull,这会导致错误。

任何人都可以帮我解决这个问题吗?

为什么是container空的?

如果可能有帮助,这是services.yml配置(Symfony 附带的默认配置):

# controllers are imported separately to make sure they're public
# and have a tag that allows actions to type-hint services
AppBundle\Controller\:
    resource: '../../src/AppBundle/Controller'
    public: true
    tags: ['controller.service_arguments']

这个问题作为问题发布在Symfony 的问题跟踪器上。

4

2 回答 2

0

此问题已由PR #23239 修复,并在Symfony 3.3.3中重新发布。

于 2017-07-26T17:29:03.713 回答
0

S3.3 自动装配功能使将控制器定义为服务变得更容易一些。

将控制器定义为服务的通常动机是避免注入容器。换句话说,您应该显式地注入控制器使用的每个服务。自动装配功能允许您使用动作方法注入,因此您不必在构造函数中注入一堆东西。

然而,基本的 Symfony 控制器类提供了一些帮助函数,它们使用了大约 12 种不同的服务。一次注射这些确实会很痛苦。我曾想过自动连线功能可能会为您解决这个问题,但我想不会。

因此,您基本上需要在服务定义中添加对 setContainer 的调用。就像是:

AppBundle\Controller\:
    resource: '../../src/AppBundle/Controller'
    public: true
    [[setContainer, ['@service_container']]]
    tags: ['controller.service_arguments']

自动装配功能在很大程度上是一项正在进行的工作,因此如果 3.4/4.0 发生这种变化,我不会感到惊讶。

于 2017-06-15T19:24:22.437 回答