borschphp/container

A simple PSR-11 Container implementation.

1.1.2 2024-05-14 19:22 UTC

This package is auto-updated.

Last update: 2024-10-14 20:16:01 UTC


README

Build Latest Stable Version License

A lightweight and easy-to-use PSR-11 container for your web projects.

Installation

Via composer :

composer require borschphp/container

Usage

use Borsch\Container\Container;

$container = new Container();

// Add your dependencies
$container->set('db', fn() => new PDO('mysql:host=localhost;dbname=mydb', 'user', 'password'));

// Retrieve your dependencies
$db = $container->get('db');

Parameterized Dependencies

In this example, we're defining a PDO service within an entry db.

Then we set the values of the parameters in the same order as the constructor :
PDO::__construct(string $dsn, ?string $username = null, ?string $password = null, ?array $options = null)) :

Finally we retrieve the PDO service.

use Borsch\Container\Container;

$container = new Container();

$container
    ->set('db', PDO::class)
    ->addParameter('mysql:host=localhost;dbname=mydb')
    ->addParameter('user')
    ->addParameter('password');

$db = $container->get('db');

Shared and Unshared Dependencies

In this example, we're defining a logger service which is shared by default.
We're retrieving the logger service twice, so we can see that the two instances are identical.

use Borsch\Container\Container;

$container = new Container();

$container
    ->set('logger', fn() => new Logger())
    ->cache(true);

$logger1 = $container->get('logger');
$logger2 = $container->get('logger');

// $logger1 and $logger2 are the same instances

Auto-wiring by default

In this example we create a custom class that requires a Logger instance to be instantiated :

class MyApp
{
    public function __construct(
        protected Logger $logger
    ) {}
}

We create an entry in the Container with Logger::class and use a closure to instantiate it.
We create an entry in the Container with MyApp::class; as we did not provide a second parameter, the container will do its best to fetch required parameters (here, a Logger) from the environment.

use Borsch\Container\Container;

$container = new Container();

$container->set(Logger::class, function () {
    $logger = new Logger('app');
    $logger->pushHandler(new StreamHandler('path/to/log/file.log'));

    return $logger;
})-> cache(true);

$container->set(MyApp::class);

$app = $container->get(MyApp::class);

// $app is instantiated with the logger from entry Logger::class

Use the container to get dependencies in a definition

Let say we have a PDO::class defined in our container and would like to use it in a Symfony CacheInterface using PdoAdapter.
We can simply get the PDO::class instance we defined by requesting it in the function parameters.

use Borsch\Container\Container;

$container = new Container();
$container->set(PDO::class, function () {
    $pdo = new PDO('sqlite:/path/to/my/database.sqlite');
    $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
    $pdo->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC);
    $pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);

    return $pdo;
})->cache(true);

$container->set(
    CacheInterface::class,
    // PDO instance defined upper will be injected here as parameter
    fn(PDO $pdo) => new PdoAdapter($pdo)
)->cache(true);

License

The package is licensed under the MIT license. See License File for more information.