最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

php - How Do I Solve: Cannot autowire service "AppCoreValidatorValidatorService" Error In Symfony 7 - Stack Ov

programmeradmin0浏览0评论

Cannot autowire service "App\Core\Validator\ValidatorService": argument "$validators" of method "__construct()" references interface "App\Core\Validator\ValidatorInterface" but no such service exists. Did you create an instantiable class that implements this interface?

How do I solve the error above.

I want to inject multiple instances of an interface into a service. See the links to two articles: Today I Learnt — How to inject multiple instances of an interface in a service and How to inject multiple instances of an interface in a service using Symfony 5

I created a 'ValidatorInterface' which I implemented in two classes, 'WelcomeEmailValidator' and 'LoginEmailValidator' classes.

I then created a Service class, to use the 'ValidatorInterface' like a service. See the code below:

<?php declare(strict_types = 1);

namespace App\Core\Validator;

use App\Core\MailStruct;

interface ValidatorInterface
{  
    /**
     * support: checks if the validator class supports this type of email 
     *
     * @param  string $type
     * @return bool
     */
    public function support(string $type): bool;

    /**
     * validate: checks if the request data is valid
     *
     * @param  MailStruct $mail
     * @return void
     */
    public function validate(MailStruct $mail): void;
}

<?php declare(strict_types = 1);

namespace App\Core\Validator;

use App\Core\EmailType;
use App\Core\MailStruct;
use App\Core\Validator\ValidatorInterface;


class LoginMessageValidator implements ValidatorInterface
{
    public function support(string $type): bool
    {
        return $type === EmailType::LOGIN_EMAIL;  
    }

    public function validate(MailStruct $mail): void
    {
        //dd(EmailType::LOGIN_EMAIL);
    }
    
}
<?php declare(strict_types = 1);

namespace App\Core\Validator;

use App\Core\EmailType;
use App\Core\MailStruct;
use App\Core\Validator\ValidatorInterface;

class WelcomeMessageValidator implements ValidatorInterface
{
    public function support(string $type): bool
    {
        return $type === EmailType::WELCOME_EMAIL;  
    }

    public function validate(MailStruct $mail): void
    {
        dd(EmailType::WELCOME_EMAIL);
    }
    
}
<?php declare(strict_types = 1);

namespace App\Core\Validator;

use App\Core\MailStruct;
use App\Core\Validator\ValidatorInterface;

class ValidatorService
{

    private ValidatorInterface $validators;

    public function __construct(ValidatorInterface $validators)
    {
        $this->validators = $validators;    
    }
    
    public function validate(MailStruct $mail)
    {
        foreach($this->validators as $validator){
            $validator->validate($mail);
        }
    }
}

I am using auto wiring for the project but for this situation, I get the error Cannot autowire service

Cannot autowire service "App\Core\Validator\ValidatorService": argument "$validators" of method "__construct()" references interface "App\Core\Validator\ValidatorInterface" but no such service exists. Did you create an instantiable class that implements this interface?

How do I solve the error above.

I want to inject multiple instances of an interface into a service. See the links to two articles: Today I Learnt — How to inject multiple instances of an interface in a service and How to inject multiple instances of an interface in a service using Symfony 5

I created a 'ValidatorInterface' which I implemented in two classes, 'WelcomeEmailValidator' and 'LoginEmailValidator' classes.

I then created a Service class, to use the 'ValidatorInterface' like a service. See the code below:

<?php declare(strict_types = 1);

namespace App\Core\Validator;

use App\Core\MailStruct;

interface ValidatorInterface
{  
    /**
     * support: checks if the validator class supports this type of email 
     *
     * @param  string $type
     * @return bool
     */
    public function support(string $type): bool;

    /**
     * validate: checks if the request data is valid
     *
     * @param  MailStruct $mail
     * @return void
     */
    public function validate(MailStruct $mail): void;
}

<?php declare(strict_types = 1);

namespace App\Core\Validator;

use App\Core\EmailType;
use App\Core\MailStruct;
use App\Core\Validator\ValidatorInterface;


class LoginMessageValidator implements ValidatorInterface
{
    public function support(string $type): bool
    {
        return $type === EmailType::LOGIN_EMAIL;  
    }

    public function validate(MailStruct $mail): void
    {
        //dd(EmailType::LOGIN_EMAIL);
    }
    
}
<?php declare(strict_types = 1);

namespace App\Core\Validator;

use App\Core\EmailType;
use App\Core\MailStruct;
use App\Core\Validator\ValidatorInterface;

class WelcomeMessageValidator implements ValidatorInterface
{
    public function support(string $type): bool
    {
        return $type === EmailType::WELCOME_EMAIL;  
    }

    public function validate(MailStruct $mail): void
    {
        dd(EmailType::WELCOME_EMAIL);
    }
    
}
<?php declare(strict_types = 1);

namespace App\Core\Validator;

use App\Core\MailStruct;
use App\Core\Validator\ValidatorInterface;

class ValidatorService
{

    private ValidatorInterface $validators;

    public function __construct(ValidatorInterface $validators)
    {
        $this->validators = $validators;    
    }
    
    public function validate(MailStruct $mail)
    {
        foreach($this->validators as $validator){
            $validator->validate($mail);
        }
    }
}

I am using auto wiring for the project but for this situation, I get the error Cannot autowire service

Share Improve this question edited Feb 5 at 19:05 Templator Khan asked Feb 3 at 14:26 Templator KhanTemplator Khan 2931 gold badge2 silver badges13 bronze badges 10
  • Should your two classes implementing this interface, not also be in the App\Core\Validator namespace? – C3roe Commented Feb 3 at 14:30
  • You tried to inject from your interface but you created 2 implementations. Which one would you expect ? Symfony can't guess it for you – AymDev Commented Feb 3 at 14:31
  • @C3roe The mistake has been corrected but the same error persist. – Templator Khan Commented Feb 3 at 14:40
  • @AymDev The mistake has been corrected but the same error persist. – Templator Khan Commented Feb 3 at 14:41
  • What mistake did you correct ? Because I see no change in the code you provided and still nothing that would answer my question in my first comment. – AymDev Commented Feb 3 at 14:51
 |  Show 5 more comments

1 Answer 1

Reset to default 2

As i wrote in my comments, the current issue is that you created an interface ValidatorInterface with multiple implementations: LoginMessageValidator & WelcomeMessageValidator. When typehinting with ValidatorInterface, Symfony cannot autowire because it does not know which implementation it should pass.

Following the articles you linked, we can see that you missed some steps in the configuration and set a wrong typing in the ValidatorService constructor: it does not need 1 implementation of the interface but multiple ones (in an array or some iterable type):

class ValidatorService
{
    /** @var ValidatorInterface[] */
    private $validators;

    /**
     * Notice the `...` operator (2nd article): allows to type arguments in a list
     * The first article suggests another typing you can also try
     */
    public function __construct(iterable $validators)
    {
        $this->validators = $validators;    
    }
    
    // ...
}

The rest of both articles work with service tagging in your config/services.yaml file.
First you want all of the classes implementing ValidatorInterface to have a tag (let's call it app.validator):

services:
    _instanceof:
        App\Core\Validator\ValidatorInterface:
            tags: ['app.validator']

Then you want every tagged service to be collected to pass them as the $validators argument of ValidatorService:

services:
    # ...
    
    App\Core\Validator\ValidatorService:
        arguments:
            $validators: !tagged_iterator app.validator

Note: Place your configurations below Symfony default configurations in the services.yaml file

与本文相关的文章

发布评论

评论列表(0)

  1. 暂无评论