F. Tomas
F. Tomas

Reputation: 198

Cannot autowire PasswordHasherInterface

I'm trying to autowire PasswordHasherInterface in the Fixtures class:

<?php
namespace App\DataFixtures;

use App\Model\User\Entity\User\Email;
use App\Model\User\Entity\User\Id;
use App\Model\User\Entity\User\Role;
use App\Model\User\Entity\User\User;
use Doctrine\Bundle\FixturesBundle\Fixture;
use Doctrine\Persistence\ObjectManager;
use Symfony\Component\PasswordHasher\PasswordHasherInterface;

class UserFixture extends Fixture
{
    private PasswordHasherInterface $hasher;

    public function __construct(PasswordHasherInterface $hasher)
    {
        $this->hasher = $hasher;
    }
    
    public function load(ObjectManager $manager): void
    {
        $hash = $this->hasher->hash("password");

        $user = User::signUpByEmail(
            Id::next(),
            new \DateTimeImmutable(),
            new Email("[email protected]"),
            $hash,
            "token"
        );

        $user->confirmSignUp();

        $user->changeRole(Role::admin());

        $manager->persist($user);
        $manager->flush();
    }
}

But I got error:

In DefinitionErrorExceptionPass.php line 54: !!
!! Cannot autowire service "App\DataFixtures\UserFixture": argument "$hasher"
!! of method "__construct()" references interface "Symfony\Component\PasswordH
!! asher\PasswordHasherInterface" but no such service exists. Did you create a
!! class that implements this interface?
!!

My file services.yaml:

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/Model/User/Entity/'
            - '../src/Kernel.php'

How to hash plain password in Symfony 6.1? Why I get this error?

Upvotes: 2

Views: 2139

Answers (1)

Chris Happy
Chris Happy

Reputation: 7295

There is no general PasswordHasher.

Either you:

  • generate a specific one using a factory: e.g. Symfony\Component\PasswordHasher\Hasher\PasswordHasherFactoryInterface
  • or you use a dedicated password hasher class: e.g. Symfony\Component\PasswordHasher\Hasher\UserPasswordHasherInterface for users*.

Using a factory, your code would look like this: (untested)

//...
use Symfony\Component\PasswordHasher\Hasher\PasswordHasherFactoryInterface;


class UserFixture extends Fixture
{
    private PasswordHasherFactoryInterface $passwordHasherFactory;

    public function __construct(PasswordHasherFactoryInterface $hasherFactory)
    {
      $this->passwordHasherFactory = $passwordHasherFactory;
    }
    
    public function load(ObjectManager $manager): void
    {
        $passwordHasher = $this->passwordHasherFactory->getPasswordHasher(User::class);
        $hash = $passwordHasher->hash("password");

        $user = User::signUpByEmail(
            Id::next(),
            new \DateTimeImmutable(),
            new Email("[email protected]"),
            $hash,
            "token"
        );

        $user->confirmSignUp();

        $user->changeRole(Role::admin());

        $manager->persist($user);
        $manager->flush();
    }

Just to reiterate, the steps are:

  1. Install the package: composer require symfony/password-hasher
  2. Configure the hasher
  3. Load a hasher
    • Load the UserPasswordHasherInterface OR
    • Load the PasswordHasherFactoryInterface (see example) and get the PasswordHasher

*: An example of UserPasswordHasherInterface for a fixure is located here.

Upvotes: 3

Related Questions