UserPasswordEncoderInterface Autowiring Not Working Symfony 4.4 - php

I have a super basic API endpoint with a fresh install of symfony 4.4 and I'm getting the following error:
Cannot autowire argument $passwordEncoder of
"App\Controller\AuthenticationController::authenticateAction()": it
references interface
"Symfony\Component\Security\Core\Encoder\UserPasswordEncoderInterface"
but no such service exists.
My Controller:
<?php
namespace App\Controller;
use App\Entity\User;
use FOS\RestBundle\Controller\AbstractFOSRestController;
use FOS\RestBundle\Controller\Annotations as Rest;
use FOS\RestBundle\Controller\Annotations\Route;
use Lexik\Bundle\JWTAuthenticationBundle\Encoder\JWTEncoderInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Security\Core\Encoder\UserPasswordEncoderInterface;
use Symfony\Component\Security\Core\Exception\CustomUserMessageAuthenticationException;
/**
* Class AuthenticationController
*
* #package App\Controller
* #Route("/api/authentication")
*/
class AuthenticationController extends AbstractFOSRestController {
/**
* #Rest\Get("/authenticate")
*
* #param Request $request
* #param UserPasswordEncoderInterface $passwordEncoder
* #param JWTEncoderInterface $JWTEncoder
*
* #return Response
*/
public function authenticateAction (Request $request, UserPasswordEncoderInterface $passwordEncoder, JWTEncoderInterface $JWTEncoder) {
exit;
}
}
If I remove UserPasswordEncoderInterface $passwordEncoder I get a successful nothing (expected for now). My User Entity is nothing special, and extends UserInterface correctly.
services.yaml
# This file is the entry point to configure your own services.
# Files in the packages/ subdirectory configure your dependencies.
# Put parameters here that don't need to change on each machine where the app is deployed
# https://symfony.com/doc/current/best_practices/configuration.html#application-related-configuration
parameters:
services:
# default configuration for services in *this* file
_defaults:
autowire: true # Automatically injects dependencies in your services.
autoconfigure: true # Automatically registers your services as commands, event subscribers, etc.
# makes classes in src/ available to be used as services
# this creates a service per class whose id is the fully-qualified class name
App\:
resource: '../src/'
exclude:
- '../src/DependencyInjection/'
- '../src/Entity/'
- '../src/Kernel.php'
- '../src/Tests/'
# controllers are imported separately to make sure services can be injected
# as action arguments even if you don't extend any base controller class
App\Controller\:
resource: '../src/Controller/'
tags: ['controller.service_arguments']
# add more service definitions when explicit configuration is needed
# please note that last definitions always *replace* previous ones
Using Symfony 4.4 and php 7.2.20
Almost certain this is some sort of configuration issue, but I'm not following what I did wrong.

Man am I smart, it was a config issue!
My security.yaml file was in main /config directory and not in the /config/packages directory. Ok maybe I'm not that smart...
Not sure how it got there. I think some out-dated package couldn't find it in the config/packages directory.
There goes 48 hours of my life...

Related

Symfony 6 - Class declared in services.yaml not found

I have a problem with registering a class as a service in services.yaml.
I have created a class MenuBuilder.php in Symfony 6 that looks somewhat like this.
src/Menu/MenuBuilder.php
namespace App\Menu;
class MenuBuilder
{
public function createMainMenu(array $options)
{
// method logic
}
}
Now, when I want to register it as a service: (and use it in twig with KnpMenuBundle)
config/services.yaml
parameters:
services:
_defaults:
autowire: true # Automatically injects dependencies in your services.
autoconfigure: true # Automatically registers your services as commands, event subscribers, etc.
App\:
resource: '../src/'
exclude:
- '../src/DependencyInjection/'
- '../src/Entity/'
- '../src/Kernel.php'
app.menu_builder:
class: App\Menu\MenuBuilder
arguments: [ "#knp_menu.factory" ]
tags:
- { name: knp_menu.menu_builder, method: createMainMenu, alias: main }
I get an error Class "App\Menu\MenuBuilder" not found.
I tried making some other classes (ex. Test/TestClass) and namespaces and it doesn't work with freshly created classes.
On the other hand it i fiddled around with the naming and it recognized my entities and factories.
I tried clearing the cache
I am in development mode
I am getting this message when calling {{ knp_menu_render('main') }} in twig.
My composer autoload:
"autoload": {
"psr-4": {
"App\\": "src/"
}
},
symfony console debug:container app.menubuilder gives me this:
Information for Service "app.menu_builder"
==========================================
---------------- -------------------------------------------------------------
Option Value
---------------- -------------------------------------------------------------
Service ID app.menu_builder
Class App\Menu\MenuBuilder
Tags knp_menu.menu_builder (method: createMainMenu, alias: main)
Public no
Synthetic no
Lazy no
Shared yes
Abstract no
Autowired yes
Autoconfigured yes
Usages knp_menu.menu_provider.lazy
---------------- -------------------------------------------------------------
! [NOTE] The "app.menu_builder" service or alias has been removed or inlined when the container was compiled.
How do i get Symfony to recognize my classses?

Symfony cannot autowire service no such service exists

UPDATE
I moved a Command from CoreBundle to AssetBundle and forgot to change the namespace path. Simply renamed /CoreBundle/Command to /AssetBundle/Command and everything worked again.
I am getting an Symfony 4.4 autowire issue that i can not resolve.
This error is about a service being injected in a helper. The helper is for the the Exporter service. The exporter service is being build by dependency injection file and there is where the helpers are getting added.
This is the defaults in my Bundle service file
services:
_defaults:
autowire: true
autoconfigure: true
public: false
This is the helper with the tag that i use
X\ExportBundle\Service\Exporter\ExportColumn\Helper\AttributeHelper:
tags:
- { name: column_helper, alias: attribute_helper }
This is the interface for the helper
class AttributeHelper implements ExportColumnHelperInterface
This is the constructor of the helper
/**
* #param EntityManagerInterface $entityManager
* #param AssetManager $assetManager
*/
public function __construct(EntityManagerInterface $entityManager, AssetManager $assetManager)
{
$this->assetManager = $assetManager;
$this->entityManager = $entityManager;
}
This is the error i get
Cannot autowire service "X\ExportBundle\Service\Exporter\ExportColumn\Helper\AttributeHelper": argument "$assetManager" of method "__construct()" references class "X\AssetBundle\Service\Asset\AssetManager" but no such service exists.
Help is very much appreciated!
Add autowire: true to the service config in yaml

controller has no container set error after chaning directory structure

I start new project and install fresh copy of Symfony 5 (microservice skeleton), and add first controller HealthCheckController to the default folder src/Controller, at this moment all is fine, I can get access to it from browser.
In next step I change a project name in composer.json and all related namespaces in code to
"autoload": {
"psr-4": {
"Project\\SubProject\\": "src/"
}
},
"autoload-dev": {
"psr-4": {
"Project\\SubProject\\Tests\\": "tests/"
}
},
and in service.yaml
Project\SubProject\:
resource: '../src/'
exclude:
- '../src/DependencyInjection/'
- '../src/Entity/'
- '../src/Kernel.php'
- '../src/Tests/'
# controllers are imported separately to make sure services can be injected
# as action arguments even if you don't extend any base controller class
Project\SubProject\Controller: # assuming you have namespace like that
resource: '../src/Controller/'
tags: [ 'controller.service_arguments' ]
everything still works.
Next step is to change directory structure, add layers and modules. So I move Kernel.php to the Common/Infrastructure/Symfony/ (ofcourse I change path to config files in the kernel) and controller to folder Common/Interfaces/Controller and change configs in the service.yaml
Project\SubProject\:
resource: '../src/'
exclude:
- '../src/Common/Infrastructure/Symfony/DependencyInjection/'
- '../src/Common/Infrastructure/Symfony/Kernel.php'
- '../src/Module1/Infrastructure/Entity/'
- '../src/Module2/Infrastructure/Entity/'
- '../src/Module3/Infrastructure/Entity/'
- '../src/Module1/Test/'
- '../src/Module2/Test/'
- '../src/Module3/Test/'
# controllers are imported separately to make sure services can be injected
# as action arguments even if you don't extend any base controller class
Project\SubProject\Common\Interfaces\Controller\: # assuming you have namespace like that
resource: '../src/Common/Interfaces/Controller/'
tags: [ 'controller.service_arguments' ]
and in routes/annotation/yaml
controllers:
resource: ../../src/Common/Interfaces/Controller
type: annotation
kernel:
resource: ../../src/Common/Infrastructure/Symfony/Kernel.php
type: annotation
and now I'm getting error Project\SubProject\Common\Interfaces\Controller\HealthCheckController" has no container set, did you forget to define it as a service subscriber?
What I'm doing wrong, I forgot to change something???
I know you can tell me you need to add container to controller like this
Project\SubProject\Common\Interfaces\Controller\HealthCheckController:
calls:
- method: setContainer
arguments: ['#service_container']
but it's stupid to configure each controller manually when autowire feature turned on, and when it worked with a default directory structure.
Also I clear cache by CLI command and manually deleting folder.
It was somewhat difficult to follow exactly what your configuration files ended as. I don't have a specific answer for you but I was a bit intrigued at the notion of moving Kernel.php. You did not mention moving the config directory so I chose to leave it where it was and:
namespace Project\SubProject\Common\Infrastructure\Symfony;
class Kernel extends BaseKernel
{
protected function configureContainer(ContainerConfigurator $container): void
{
$base = $this->getProjectDir();
$container->import($base . '/config/{packages}/*.yaml');
$container->import($base . '/config/{packages}/'.$this->environment.'/*.yaml');
$container->import($base . '/config/services.yaml');
$container->import($base . '/config/{services}_'.$this->environment.'.yaml');
}
# same for configureRoutes
# project/config/services.yaml
services:
_defaults:
autowire: true
autoconfigure: true
Project\SubProject\:
resource: '../src/'
exclude:
- '../src/Common/Infrastructure/Symfony/Kernel.php'
Project\SubProject\Common\Interfaces\Controller\:
resource: '../src/Common/Interfaces/Controller/'
tags: ['controller.service_arguments']
# project/config/routes/annotations.yaml
controllers:
resource: ../../src/Common/Interfaces/Controller/
type: annotation
Tweaked index.php and console to use the new Kernel path and it all worked as expected.
I should point out that as long as you are extending from AbstractController then you don't actually need the Controller section in services.yaml at all. It's quite puzzling why you seem to be getting a controller service but setContainer is not being called.
bin/console debug:container HealthCheckController
Class Project\SubProject\Common\Interfaces\Controller\HealthCheckController
Tags controller.service_arguments
container.service_subscriber
Calls setContainer
The Calls setContainer is obviously the important line.
I'm guessing you do have a typo somewhere and I suspect you did not actually start your namespace with Project\SubProject. But again it does work as expected.
Just for my own reference I checked in my test project.

Autowire not working in Symfony's Dependency Injection component

I am using Symfony's Dependency Injection component version 3.4 in my custom PHP project. My project is running on PHP 5.6
"symfony/dependency-injection": "^3.4"
I have defined my services.yaml file to contain following service definitions
logger:
class: Monolog\Logger
arguments: ["application"]
autowire: true
public: true
Monolog\Logger: '#logger'
plugin_context:
class: MyProject\PluginContext
autowire: true
public: true
I can confirm that the autoloading is working and the instance of both classes are present in the definition, but the Logger class is not autowired in PluginContext constructor. the class is defined in the following code
use Monolog\Logger;
class PluginContext
{
private $logger;
function __construct(Logger $logger) {
$this->logger = $logger;
}
}
When the following code is run, PHP throws an exception
$container->get("plugin_context");
Catchable fatal error: Argument 1 passed to MyProject\PluginContext::__construct() must be an instance of Monolog\Logger, none given
Change your FQCN $logger and use this one use Psr\Log\LoggerInterface instead Monolog\Logger
Another thing, thanks to autowiring you don't need to specify anything in service.yaml except this (the default configuration):
_defaults:
autowire: true # Automatically injects dependencies in your services.
autoconfigure: true # Automatically registers your services as commands, event subscribers, etc.
public: false # Allows optimizing the container by removing unused services; this also means
# fetching services directly from the container via $container->get() won't work.
# The best practice is to be explicit about your dependencies anyway.
# makes classes in src/ available to be used as services
# this creates a service per class whose id is the fully-qualified class name
App\:
resource: '../src/*'
exclude: '../src/{Entity,Migrations,Tests,Kernel.php}'
The Doc said : « Aliases are used by the core bundles to allow services to be autowired. For example, MonologBundle creates a service whose id is logger. But it also adds an alias: Psr\Log\LoggerInterface that points to the logger service. This is why arguments type-hinted with Psr\Log\LoggerInterface can be autowired » so in your case the Psr\Log\LoggerInterface is an alias for Monolog https://symfony.com/doc/current/service_container/autowiring.html#using-aliases-to-enable-autowiring
It seems that the either the contents of services.yaml are not full.
Your services file should be like this
services:
logger:
class: Monolog\Logger
arguments: ["application"]
autowire: true
public: true
Monolog\Logger: '#logger'
plugin_context:
class: MyProject\PluginContext
autowire: true
public: true

Symfony 4 - The autoloader expected class […] to be defined in file

I'm trying to add an old Bundle that I have built on Symfony 3.* to Symfony 4 but I get this error:
The autoloader expected class
"App\SBC\TiersBundle\Controller\ChantierController" to be defined in
file
"/Applications/MAMP/htdocs/Projects/HelloSymfony4/vendor/composer/../../src/SBC/TiersBundle/Controller/ChantierController.php".
The file was found but the class was not in it, the class name or
namespace probably has a typo in
/Applications/MAMP/htdocs/Projects/HelloSymfony4/config/services.yaml
(which is loaded in resource
"/Applications/MAMP/htdocs/Projects/HelloSymfony4/config/services.yaml").
It seems like the framework did not recognise the namespace of the bundle so I did these steps:
In config/bundle.php I added the third line:
return [
Symfony\Bundle\FrameworkBundle\FrameworkBundle::class => ['all' => true],
Symfony\Bundle\TwigBundle\TwigBundle::class => ['all' => true],
\SBC\TiersBundle\TiersBundle::class => ['all' => true], // this one
Symfony\Bundle\WebProfilerBundle\WebProfilerBundle::class => ['dev' => true, 'test' => true],
];
And in composer.json I added the first line in autoload section:
"autoload": {
"psr-4": {
"SBC\\": "src/SBC/",
"App\\": "src/"
}
},
Because the namespace of my Bundle starts with SBC\, and I have launched composer dump-autoload in the console.
<?php
namespace SBC\TiersBundle;
use Symfony\Component\HttpKernel\Bundle\Bundle;
class TiersBundle extends Bundle
{
}
ChantierController.php:
namespace SBC\TiersBundle\Controller;
use SBC\TiersBundle\Entity\Chantier;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
class ChantierController extends Controller
{
...
}
And this is my Bundle under /src:
Unfortunately still facing the same error, how can I fix it and thanks in advance.
UPDATE: config/services.yaml:
# Put parameters here that don't need to change on each machine where the app is deployed
# https://symfony.com/doc/current/best_practices/configuration.html#application-related-configuration
parameters:
services:
# default configuration for services in *this* file
_defaults:
autowire: true # Automatically injects dependencies in your services.
autoconfigure: true # Automatically registers your services as commands, event subscribers, etc.
public: false # Allows optimizing the container by removing unused services; this also means
# fetching services directly from the container via $container->get() won't work.
# The best practice is to be explicit about your dependencies anyway.
# makes classes in src/ available to be used as services
# this creates a service per class whose id is the fully-qualified class name
SBC\:
resource: '../src/SBC/*'
exclude: '../src/SBC/TiersBundle/{Entity,Migrations,Tests}'
SBC\TiersBundle\Controller\:
resource: '../src/SBC/TiersBundle/Controller'
tags: ['controller.service_arguments']
App\:
resource: '../src/*'
exclude: '../src/{Entity,Migrations,Tests}'
# controllers are imported separately to make sure services can be injected
# as action arguments even if you don't extend any base controller class
App\Controller\:
resource: '../src/Controller'
tags: ['controller.service_arguments']
# add more service definitions when explicit configuration is needed
# please note that last definitions always *replace* previous ones
The problem is most likely caused by Symfony configuration and conflict in namespaces. First you need to adjust your config/services.yaml:
SBC\:
resource: '../src/SBC/*'
exclude: '../src/SBC/TiersBundle/{Entity,Migrations,Tests,Kernel.php}'
SBC\TiersBundle\Controller\:
resource: '../src/SBC/TiersBundle/Controller'
tags: ['controller.service_arguments']
App\:
resource: '../src/*'
exclude: '../src/{SBC,Entity,Migrations,Tests,Kernel.php}'
This way you'll define defaults for your namespace and prevent the default namespace App to include your directory when generating autoload classes. Note that if you are using annotation routes, you also need to adjust config/routes/annotations.yaml:
sbc_controllers:
resource: ../../src/SBC/TiersBundle/Controller/
type: annotation
so the routes are generated correctly. After performing these steps run composer dump-autoload again and clear Symfony's cache.
This might be helpful in the future if you run into another problems: https://github.com/symfony/symfony/blob/master/UPGRADE-4.0.md

Categories