Dependency injection for a bundle controller

末鹿安然 提交于 2019-12-11 19:53:13

问题


I have a simple, working SecurityController that I would like to turn into a bundle so that I can share basic authentication functionality across a few basic websites I create. Everything is working as desired until I try to turn my code into a bundle.

I have created my bundle class, a Resources/config/routing.xml file to declare my login and logout routes, have a template in Resources/views/Security/login.html.twig but the following class is throwing an error.

<!-- Controller/SecurityController.php -->
<?php

namespace JustinVoelker\EssentialSecurityBundle\Controller;

use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\Security\Http\Authentication\AuthenticationUtils;

class SecurityController extends AbstractController
{
    private $authenticationUtils;

    public function __construct(AuthenticationUtils $authenticationUtils)
    {
        $this->authenticationUtils = $authenticationUtils;
    }

    public function loginAction()
    {
        $error = $this->authenticationUtils->getLastAuthenticationError();

        return $this->render('@EssentialSecurity/Security/login.html.twig', [
            'error' => $error,
        ]);
    }

    ... Comments and additional functions removed for simplicity

}

The error I am getting when I go to the login page is Controller "JustinVoelker\EssentialSecurityBundle\Controller\SecurityController" has required constructor arguments and does not exist in the container. Did you forget to define such a service?

Following a few different examples/tutorials, I tried creating a services.xml file and loading it via DependencyInjection/EssentialSecurityExtension.php in an attempt to make AuthenticationUtils available to my constructor but that does not appear to change anything.

<!-- DependencyInjection/EssentialSecurityExtension.php -->
<?php

namespace JustinVoelker\EssentialSecurityBundle\DependencyInjection;

use Symfony\Component\Config\FileLocator;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Extension\Extension;
use Symfony\Component\DependencyInjection\Loader\XmlFileLoader;

class EssentialSecurityExtension extends Extension
{
    public function load(array $configs, ContainerBuilder $container)
    {
        $loader = new XmlFileLoader(
            $container,
            new FileLocator(__DIR__.'/../Resources/config')
        );
        $loader->load('services.xml');
    }
}
<!-- Resources/config/services.xml -->
<?xml version="1.0" encoding="UTF-8" ?>

<container xmlns="http://symfony.com/schema/dic/services"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd">
    <services>
        <service id="essential_security.controller"
                 class="JustinVoelker\EssentialSecurityBundle\Controller\SecurityController">
            <argument type="service" id="security.authentication_utils"/>
        </service>
    </services>
</container>

What am I missing that allows me to use dependency injection inside a bundle as I was able to before moving this code into a bundle?

If I simply remove any reference to AuthenticationUtils (the private property, the entire constructor, and its usage inside loginAction) the page renders, though it will not function as desired without that last authentication error that I am using AuthenticationUtils for in the first place.

Side note, if I manually add JustinVoelker\EssentialSecurityBundle\Controller\SecurityController: ~ to my applications main config/services.xml file, The controller error disappears so clearly I'm missing something inside my bundle to make this work.

Perhaps there is another way to achieve my ultimate end goal of returning the last authentication error message to the login page, but my question is what am I missing that is preventing this dependency injection from working as it did before I bundled my controller and as it appears to work in so many examples I've seen.

EDIT 2019-05-30 Including a portion of my original routing.xml

<route id="essential_security_login" path="/login">
    <default key="_controller">EssentialSecurityBundle:Security:login</default>
</route>

回答1:


Looks like in your routing you use JustinVoelker\EssentialSecurityBundle\Controller\SecurityController but your service name is essential_security.controller You should either change your routing or service definition

You can add an alias

<!-- Resources/config/services.xml -->
<service id="JustinVoelker\EssentialSecurityBundle\Controller\SecurityController" alias="essential_security.controller"/>

<service id="essential_security.controller" class="JustinVoelker\EssentialSecurityBundle\Controller\SecurityController">
    <argument type="service" id="security.authentication_utils"/>
    <tag name="controller.service_arguments"/>
</service>

or just rename it (note you can omit class parameter)

<!-- Resources/config/services.xml -->
<service id="JustinVoelker\EssentialSecurityBundle\Controller\SecurityController">
    <argument type="service" id="security.authentication_utils"/>
    <tag name="controller.service_arguments"/>
</service>

or in your routing:

route_name:
    path:     /path
    controller: JustinVoelker\EssentialSecurityBundle\Controller\SecurityController::loginAction
route_name:
    path:     /path
    controller: essential_security.controller::loginAction

depends on your service name



来源:https://stackoverflow.com/questions/56370800/dependency-injection-for-a-bundle-controller

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!