Symfony: Autowiring failed while it doesn't seem necessary (must have a type-hint or be given a value explicitly.)

Created on 14 Jun 2017  路  3Comments  路  Source: symfony/symfony

| Q | A
| ---------------- | -----
| Bug report? | yes
| Feature request? |no
| BC Break report? |no
| RFC? |no
| Symfony version | 3.3

Edit: after some more reading I believe I should just disable autowiring for the used folders (for example the Doctrine folder). I was under the impression that autowiring only was executed when a class didn't have a service yet.

Running on a default installation of Symfony 3.3, and I didn't change anything in app/config/services.yml. Even though I am running into this issue while using FOS Userbundle, I believe the issue is related to symfony itself, or I am doing something wrong.

The issue:

I need a custom UserManager, so I created a class AppBundle\Doctrine\UserManager which extends FOS\UserBundle\Doctrine\UserManager.

The service is configured like this:

app.doctrine.manager.user_manager:
    public: false
    class: AppBundle\Doctrine\UserManager
    arguments:
        - "@fos_user.util.password_updater"
        - "@fos_user.util.canonical_fields_updater"
        - "@fos_user.object_manager"
        - '%fos_user.model.user.class%'

In app/config I defined this:

fos_user:
    db_driver: orm
    firewall_name: api
    user_class: AppBundle\Entity\User
    from_email:
        address: "%mailer_user%"
        sender_name: "%mailer_user%"
    service:
        user_manager: 'app.doctrine.manager.user_manager'

The error:

PHP Fatal error:  Uncaught Symfony\Component\DependencyInjection\Exception\AutowiringFailedException: Cannot autowire service "AppBundle\Doctrine\UserManager": argument "$class" of method "FOS\UserBundle\Doctrine\UserManager::__construct()" must have a type-hint or be given a value explicitly.

The constructor of FOS (which I originally didn't override) looks like this:

/**
 * Constructor.
 *
 * @param PasswordUpdaterInterface $passwordUpdater
 * @param CanonicalFieldsUpdater   $canonicalFieldsUpdater
 * @param ObjectManager            $om
 * @param string                   $class
 */
public function __construct(PasswordUpdaterInterface $passwordUpdater, CanonicalFieldsUpdater $canonicalFieldsUpdater, ObjectManager $om, $class)
{
    parent::__construct($passwordUpdater, $canonicalFieldsUpdater);

    $this->objectManager = $om;
    $this->class = $class;
}

Debug:

To me it looks like I autowiring shouldn't have done anything here, no? When I look into the compiler pass of FOSUser, they just create an alias to my own service.

For now I can resolve this problem by overriding the __construct method, and adding = '' to the $class argument and then everything works just fine.

/**
 * Constructor.
 *
 * @param PasswordUpdaterInterface $passwordUpdater
 * @param CanonicalFieldsUpdater   $canonicalFieldsUpdater
 * @param ObjectManager            $om
 * @param string                   $class
 */
public function __construct(PasswordUpdaterInterface $passwordUpdater, CanonicalFieldsUpdater $canonicalFieldsUpdater, ObjectManager $om, $class = '')
{
    parent::__construct($passwordUpdater, $canonicalFieldsUpdater, $om, $class);
}
Bug DependencyInjection Needs Review

Most helpful comment

your PSr-4 loading defines an autowired service with id AppBundle\Doctrine\UserManager. your own explicit config defines a service with id app.doctrine.manager.user_manager.

So you still have the autowired service needing some explicit config.
you have 2 choices to solve it:

  • ignore the folder in your PSR-4 import so that the AppBundle\Doctrine\UserManager service does not get created
  • use AppBundle\Doctrine\UserManager as id when configuring the service explicitly, so that it overwrites the service defined by the PSR-4 import (instead of keeping both)

All 3 comments

your PSr-4 loading defines an autowired service with id AppBundle\Doctrine\UserManager. your own explicit config defines a service with id app.doctrine.manager.user_manager.

So you still have the autowired service needing some explicit config.
you have 2 choices to solve it:

  • ignore the folder in your PSR-4 import so that the AppBundle\Doctrine\UserManager service does not get created
  • use AppBundle\Doctrine\UserManager as id when configuring the service explicitly, so that it overwrites the service defined by the PSR-4 import (instead of keeping both)

closing since there is no bug

@stof thanks, I misinterpreted the autowiring functionality. It is solved now.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

kherrera-ebsco picture kherrera-ebsco  路  3Comments

FRAGnatt picture FRAGnatt  路  3Comments

wouterj picture wouterj  路  3Comments

slashsbin picture slashsbin  路  3Comments

patrick-mcdougle picture patrick-mcdougle  路  3Comments