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

Installation

The container can be installed using composer:

composer require jason-napolitano/psr11-container

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) { 
    // ...
});

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. It is important to note that any services that you intend to mount into the service container MUST implement the MountableInterface in order to load properly. If the MountableInterface is not implemented, a ContainerException will be thrown.

namespace App\Services;

class Session implements ContainerFactory\Contracts\MountableInterface
{
    public function __construct(protected bool $autoStart)
    {
        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];
    }
}

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.

For example - let's say we are creating a micro-framework. We might want to implement a portable container. Then, we may want to instantiate that container in the apps bootstrap process, and add dependencies to it later on. Go here to see our super complicated session library that we mount to the container in the example below.

use function ContainerFactory\instance;

// further up the tree a new container has been instantiated
// ...

// a whole lot of other cool things have already happened, and
// are happening still
// ...

// now, we can mount a new session library using
// instance()->mount()
instance()->mount([
    'session' => \App\Services\Session::class
]);

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

Alternately, 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();
Clone this wiki locally