php-fig / container

MIT License
9.93k stars 52 forks source link

Question: Why there is no set method? #46

Open tbreuss opened 1 year ago

tbreuss commented 1 year ago

Why doesn't the interface provide a "set" method? I wonder what the use case for the interface is if I can't rely on a contract about how objects can be stored in the container?

See similar question on SO at https://stackoverflow.com/q/61504435/6161354.

Thanks for clarifying.

mnapoli commented 1 year ago

Hi, this is explained in this document here: https://www.php-fig.org/psr/psr-11/meta/#31-goals

Hope that answers your question!

tbreuss commented 1 year ago

Thanks for clarifying and sorry for the rtfm thing. I had a different expectation and simply was surprised that the set method is not included.

In simplified terms, could one say that the target audience for the container interface are authors of libraries or frameworks and not authors of concrete applications where the application itself is responsible for filling the container?

mnapoli commented 1 year ago

Exactly yes.

cottton commented 1 year ago

Not so nice. What about a framework building dev? Perhaps we want to swap the Di too? :)

Simple example:

$config = [
    // ...
    'di'          => [
        // class: MUST implement a \Psr\Container\ContainerInterface.
        # DISABLED - buggy. Using Awesome Di now.
        # 'class' => \Foo\Bar\Di::class,
        'class'   => \Awesome\Di::class,
        'options' => [
            // ...
        ],
    ],
    'cache'       => [
        'class'        => \Foo\Bar\Cache::class,
        'options'      => [
            // ...
        ],
        'is_singleton' => true,
    ],
    'http_client' => [
        'class'        => \Foo\Bar\Http\Client::class,
        'options'      => [
            // ...
        ],
        'is_singleton' => false,
    ],
];

class App
{
    /**
     * @var \Psr\Container\ContainerInterface
     */
    protected $di;

    /**
     * @param array $config
     */
    public function __construct(array $config)
    {
        // Set app di.
        $class = $config['di']['class'];
        $options = $config['di']['options'];
        $this->setDi(new $class($options));

        // Set cache on di.
        $lazyLoadCallable = function () use ($config) {
            $class = $config['cache']['class'];
            $options = $config['cache']['options'];
            return new $class($options);
        };
        $this->getDi()->setSingleton($lazyLoadCallable);
        // or
        // $this->getDi()->setShared($lazyLoadCallable);
        // or
        // $shared = true;
        // $this->getDi()->set($lazyLoadCallable, $shared);
        // or
        // $shared = true;
        // $lazy = true;
        // $this->getDi()->set([$class, $options], $shared, $lazy);

        // Set http client on di.
        $class = $config['http_client']['class'];
        $options = $config['http_client']['options'];
        $shared = false;
        $lazy = true;
        $this->getDi()->set([$class, $options], $shared, $lazy);
    }

    /**
     * @param \Psr\Container\ContainerInterface $di
     *
     * @return App
     */
    public function setDi(\Psr\Container\ContainerInterface $di): App
    {
        $this->di = $di;
        return $this;
    }

    /**
     * @return \Psr\Container\ContainerInterface
     */
    public function getDi(): \Psr\Container\ContainerInterface
    {
        return $this->di;
    }
}

Perhaps we can get a \Psr\Container\Dependency\Injection\DiInterface ?

mnapoli commented 1 year ago

@cottton this would be a separate PSR, I don't think it's worth discussing here because this PSR is not about that. It will never happen in this PSR specifically.

robopzet commented 1 year ago

Is a standard for DI configuration worked on? To find the best implementation you now have to learn how each package works. A common setup syntax would fix that.

delboy1978uk commented 7 months ago

With my own framework I simply extended pimple but created a RegistrationInterface with a method public function addToContainer(Container $c): void;, I call it Barnacle because it's stuck to a lot of my code until there's something that deals with this in a better way https://github.com/delboy1978uk/barnacle/blob/master/src/RegistrationInterface.php