Skip to content
Jason Napolitano edited this page Sep 21, 2024 · 68 revisions

Installation

The container can be installed using composer:

composer require jason-napolitano/psr11-container

Example library

In the docs, we'll use a session library as an example on how to properly mount a dependency and interact with it. Out of solidarity for a clean example of what we're doing in the tutorial, this is the class we will be using.

namespace App\Services;

class Session
{
    public function __construct(protected bool $autoStart = false)
    {
        if ($this->autoStart) session_start();
    }

    public function set(string $key, mixed $value): void
    {
        $_SESSION[$key] = $value;
    }
    
    public function get(string $key): mixed
    {
        return $_SESSION[$key];
    }
}

Building a container

Building a container is simple. To do so we need to call the container() function. In the container, an optional callback can be passed which returns the container instance. Omitting the callback will allow a new container to be instantiated without any initial dependencies (the container can then be called later on using the instance() helper).

use ContainerFactory\Contracts;

use function ContainerFactory\{container};

// the callback is optional
container(function (Contracts\ContainerInterface $container) { 
    $container->mount([
        'session' => \App\Services\Session::class
    );
});

Passing arguments

There will be times where we'd like to pass arguments to the constructor of a class that will be used as a service. To do this, we simply have to assign an anonymous function as the value of the service when mounting it to the container. Then, we would return an object of that class and pass the arguments through that we will want to use each time we call the service.

use ContainerFactory\Contracts;

use function ContainerFactory\{container};

// the callback is optional
container(function (Contracts\ContainerInterface $container) { 
    $container->mount([
        'session' => fn() => new Session(autoStart: true)
    );
});

Accessing the container

Accessing the current container instance can be done by calling instance(). This function takes no arguments. The instance() helper allows us to interact with the container at any time. The object returned is a container instance that conforms to the InstanceInterface contract, and therefor gives us access to all of the functions that may be used on that container.

use function ContainerFactory\{instance};

// mount an array of dependencies
instance()->mount(...);

// add a single dependency
instance()->add(...);

// remove a dependency
instance()->remove(...);

// reset a container
instance()->reset();

// destroy a container
instance()->destroy();

Accessing dependencies

Okay, so we've mounted a session library to our container, and we want to access a shared instance of that library. To do this, we will simply call the service() function . This function takes one argument - the key for the mounted dependency - EG: session as we've configured in the example above.

use function ContainerFactory\{service};

$session = service('session');

$session->set('message', 'Your account has been created');

echo $session->get('message'); // Your account has been created

Alternatively, we can call the service class directly and access the services from there.

use ContainerFactory\Service;

$session = Service::session();

$session->set('message', 'Your account has been created');

echo $session->get('message'); // Your account has been created

Resetting the container

We can easily reset the container, and all its properties. Doing so will remove all dependencies and give us a new container object. To do this we would call instance()->reset().

use function ContainerFactory\{instance};

instance()->reset();

Destroying the container

There will be times when we may want to destroy a container. Destroying a container instance will completely destroy the container object; rendering it useless.

use function ContainerFactory\{instance};

instance()->destroy();