PHP - Create Dependency Injection Container PSR-11 like PHP-DI (DI)

fadymr

F.R Michel

Posted on January 23, 2021

PHP - Create Dependency Injection Container PSR-11 like PHP-DI (DI)

PHP Dependency Injection Container PSR-11

Install the standard interfaces for Container.:

composer require psr/container
Enter fullscreen mode Exit fullscreen mode

Let's create the class that will implement the containerInterface

<?php

namespace DevCoder\DependencyInjection;

use DevCoder\DependencyInjection\Exception\NotFoundException;
use Psr\Container\ContainerExceptionInterface;
use Psr\Container\ContainerInterface;
use Psr\Container\NotFoundExceptionInterface;

class Container implements ContainerInterface
{
    /**
     * @var array
     */
    private $definitions = [];

    /**
     * @var array
     */
    private $resolvedEntries = [];

    public function __construct(array $definitions)
    {
        $this->definitions = array_merge(
            $definitions,
            [ContainerInterface::class => $this]
        );
    }

    /**
     * Finds an entry of the container by its identifier and returns it.
     *
     * @param string $id Identifier of the entry to look for.
     *
     * @return mixed Entry.
     * @throws ContainerExceptionInterface Error while retrieving the entry.
     *
     * @throws NotFoundExceptionInterface  No entry was found for **this** identifier.
     */
    public function get($id)
    {
        if (!$this->has($id)) {
            throw new NotFoundException("No entry or class found for '$id'");
        }

        if (array_key_exists($id, $this->resolvedEntries)) {
            return $this->resolvedEntries[$id];
        }

        $value = $this->definitions[$id];
        if ($value instanceof \Closure) {
            $value = $value($this);
        }

        $this->resolvedEntries[$id] = $value;
        return $value;
    }

    /**
     * Returns true if the container can return an entry for the given identifier.
     * Returns false otherwise.
     *
     * `has($id)` returning true does not mean that `get($id)` will not throw an exception.
     * It does however mean that `get($id)` will not throw a `NotFoundExceptionInterface`.
     *
     * @param string $id Identifier of the entry to look for.
     *
     * @return bool
     */
    public function has($id)
    {
        return array_key_exists($id, $this->definitions) || array_key_exists($id, $this->resolvedEntries);
    }
}

Enter fullscreen mode Exit fullscreen mode

Let's create the class that will implement the NotFoundExceptionInterface

<?php

namespace DevCoder\DependencyInjection\Exception;

use Psr\Container\NotFoundExceptionInterface;

/**
 * Class NotFoundException
 * @package DevCoder\DependencyInjection\Exception
 */
class NotFoundException extends \InvalidArgumentException implements NotFoundExceptionInterface
{
}

Enter fullscreen mode Exit fullscreen mode

How to use ?

// services.php
<?php

use Psr\Container\ContainerInterface;

return [
    'database.host' => '127.0.0.1',
    'database.port' => null,
    'database.name' => '',
    'database.user' => 'root',
    'database.password' => null,
    'google.key' => 'YQ4FcwaXD165Xm72lx53qzzNzkz7AUUN',
    PDO::class => static function (ContainerInterface $container) {
        return new PDO(
            sprintf('mysql:host=%s;dbname=%s;', $container->get('database.host'), $container->get('database.name')),
            $container->get('database.user'),
            $container->get('database.password'),
            [PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION]
        );
    },
];
Enter fullscreen mode Exit fullscreen mode
<?php

use DevCoder\DependencyInjection\Container;

$services = require 'services.php';
$container = new Container($services);

var_dump($container->get(PDO::class));
// object(PDO)[18]


var_dump($container->get('google.key'));
// YQ4FcwaXD165Xm72lx53qzzNzkz7AUUN
Enter fullscreen mode Exit fullscreen mode

Ideal for small project
Simple and easy!
https://github.com/devcoder-xyz/php-dependency-injection

How can we improve this object?

  • add autowire option to Auto resolution of constructor parameters
💖 💪 🙅 🚩
fadymr
F.R Michel

Posted on January 23, 2021

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related