thephpleague / container

Small but powerful dependency injection container

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

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Feature: Delegate container for discoverable providers/factories

adrianmiu opened this issue · comments

I am using this library in my some projects and I would like to see this feature added.

Most of the times the container is used to retrieve and instance of a class. For this situations I use another class with the "Factory" suffix which implements an interface like this

interface FactoryInterface
{
    /**
     * Creates an object based on the alias
     * Depending on the needs of the application it can return
     * a new object on each invocation or the same object
     *
     * @param ContainerInterface $container
     * @return mixed
     */
    public function __invoke(ContainerInterface $container);
}

So, when the container requires the App\Mail\Sender class, the delegate container looks for App\Mail\SenderFactory class and uses it to return the object

I have also created another interface that allows a static method for a class to act as the factory.

interface StaticFactoryMethodInterface
{
    public static function factory(ContainerInterface $app);
}

In this case the delegate container checks if the class implements this interface and uses it to produce the desired service.

I can implement this feature if you'd like

I'm curious as to what problem this solves over just creating a definition in the container?

Service providers solve a problem that a definition in the container doesn't, right? It lets your app make use of 3rd party packages for once.

However the service providers must be registered. Since these factories would be similar to a single-class provider (ie: 1 provider for 1 class) we can use a naming convention to let the delegate container discover single-class provider so you don't have to manually register them.

Now, your question made think more about it and it seems it would be trivial to implement this auto-discover-ability feature by using the current implementation of providers instead of the factory interface I've proposed. So for the App\Mail\Sender class you could create a App\Mail\SenderProvider with the following code

namespace App\Mail;

class SenderProvider extends League\Container\ServiceProvider\AbstractServiceProvider {

   protected $provides = ['App\Mail\Sender'];

   public function register()
   {
        $this->getContainer()
                ->add('App\Mail\Sender')
                ->addArgument('param1')
                ->addArgument('param2');
       }
    }
}