thephpleague / container

Small but powerful dependency injection container

Home Page:http://container.thephpleague.com

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Question: How to achieve autowiring inside the service provider?

creative-andrew opened this issue · comments

commented

Hello ,

Based on your example of the register method of the service provider, we need to explicitly define dependencies/arguments to add the class to the container.

   public function provides(string $id): bool
    {
        $services = [
            Some\Controller::class, // class with Request and Model as dependencies.
        ];
        
        return in_array($id, $services);
    }
    
    public function register(): void
    {
        $this->getContainer()->add('key', 'value');

        $this->getContainer()
            ->add(Some\Controller::class)
             ->addArgument(Some\Request::class)
             ->addArgument(Some\Model::class)
    } 

I was wondering if it is possible to just add the class provided in the services array and let the container resolve/auto-wire. Namely, to be able to just do the following:

    public function register(): void
    {

        $this->getContainer()
            ->add(Some\Controller::class)
    } 

I am trying to make the container call a method init on all the services defined within the service provider. For example:

Container:

final class Container {

    private $service_providers = [
        TestServiceProvider::class
    ];

    private $container;

    public function __construct() {
        $this->container = new LeageContainer();

        $this->container->delegate(
            new ReflectionContainer()
        );

        foreach ($this->service_providers as $service_provider_class) {
            $service_provider = new $service_provider_class();
            $this->container->addServiceProvider($service_provider);
            foreach ($service_provider->getServices() as $service) {
                $this->container->get($service)->init();
            }
        }
    }
   ...
}

ServiceProvider

class TestServiceProvider extends AbstractServiceProvider {
     private $current_service_being_procces = '';
     
     private $services = [
          TestService::class => TestService::class,
      ];

    public function getServices() {
        return $this->services;
    }
    
   public function provides(string $id): bool {
        if (isset($this->getServices()[$id])) {
            $this->current_service = $this->getServices()[$id];
            return true;
        }
        return false;
    }
    
   public function register(): void {
        $this->getContainer()->add($this->current_service);
    }

}

TestService:

class TestService {
    public function __construct(TestService2 $testService2) {
        $this->testService2 = $testService2;
    }
    public function init() {
        echo "hi";
        $this->testService2->bye();
    }
}
$container = (new Container());
Fatal error: Uncaught ArgumentCountError: Too few arguments to function \Container\ServiceProvider\TestService::__construct(), 0 passed and exactly 1 expected