Skip to content
Snippets Groups Projects
DI.php 3.57 KiB
Newer Older
Thomas Flori's avatar
Thomas Flori committed
<?php

namespace DependencyInjector;

/**
 * Class DependencyInjector
 *
 * This is a Dependency Injector. It gives the opportunity to define how to get a dependency from outside of the code
 * that needs the dependency. This is especially helpful for testing proposes when you need to mock a dependency.
 *
 * You can never get an instance of this class. For usage you have only two static methods.
 *
 * Example usage:
 * DependencyInjector::set('hello', function() { return 'hello'; });
 * DependencyInjector::set('world', function() { return 'world'; });
 * echo DependencyInjector:get('hello') . " " . DependencyInjector:.get('world') . "!\n";
 */
Thomas Flori's avatar
Thomas Flori committed
class DI
{
    protected static $instances     = [];
    protected static $dependencies = [];

    /**
     * Get a previously defined dependency identified by $name.
     *
     * @param string $name
Thomas Flori's avatar
Thomas Flori committed
     * @return mixed
Thomas Flori's avatar
Thomas Flori committed
    public static function get($name)
    {
        if (isset(self::$instances[$name])) {
            return self::$instances[$name];
        } elseif (isset(self::$dependencies[$name])) {
            if (self::$dependencies[$name]['singleton']) {
                self::$instances[$name] = call_user_func(self::$dependencies[$name]['getter']);
                return self::$instances[$name];
Thomas Flori's avatar
Thomas Flori committed
            return call_user_func(self::$dependencies[$name]['getter']);
Thomas Flori's avatar
Thomas Flori committed

        } elseif (class_exists($name)) {
Thomas Flori's avatar
Thomas Flori committed
            $reflection = new \ReflectionClass($name);

            if ($reflection->getName() === $name) {
Thomas Flori's avatar
Thomas Flori committed
                self::$instances[$name] = $name;
                return self::$instances[$name];
        throw new Exception("Unknown dependency '" . $name . "'");
Thomas Flori's avatar
Thomas Flori committed

    /**
     * Alias for DI::get($name). Example:
     * DI::get('same') === DI::same()
     *
     * @param string $name
     * @param array  $arguments
     * @return mixed
     */
Thomas Flori's avatar
Thomas Flori committed
    public static function __callStatic($name, $arguments)
    {
Thomas Flori's avatar
Thomas Flori committed
        return self::get($name);
    }

    /**
     * Define a dependency.
     *
     * @param string $name
Thomas Flori's avatar
Thomas Flori committed
     * @param mixed  $getter    The callable getter for this dependency or the value
     * @param bool   $singleton Save result from $getter for later request
     * @param bool   $isValue   Store $getter as value
Thomas Flori's avatar
Thomas Flori committed
     * @return void
     */
Thomas Flori's avatar
Thomas Flori committed
    public static function set($name, $getter, $singleton = true, $isValue = false)
    {
Thomas Flori's avatar
Thomas Flori committed
        if (!$isValue && is_callable($getter)) {
            if (isset(self::$instances[$name])) {
                unset(self::$instances[$name]);
Thomas Flori's avatar
Thomas Flori committed
            self::$dependencies[$name] = [
Thomas Flori's avatar
Thomas Flori committed
                'singleton' => $singleton,
Thomas Flori's avatar
Thomas Flori committed
                'getter'    => $getter
Thomas Flori's avatar
Thomas Flori committed
            ];
        } else {
Thomas Flori's avatar
Thomas Flori committed
            self::$instances[$name] = $getter;
Thomas Flori's avatar
Thomas Flori committed
        }
    }

    /**
     * Resets the DependencyInjector
     *
     * @return void
     */
Thomas Flori's avatar
Thomas Flori committed
    public static function reset()
    {
Thomas Flori's avatar
Thomas Flori committed
        self::$instances     = [];
        self::$dependencies = [];
Thomas Flori's avatar
Thomas Flori committed
    }

    /**
     * Removes dependency $name
     *
     * @param string $name
     */
Thomas Flori's avatar
Thomas Flori committed
    public static function unset($name)
    {
Thomas Flori's avatar
Thomas Flori committed

Thomas Flori's avatar
Thomas Flori committed
        if (isset(self::$instances[$name])) {
            unset(self::$instances[$name]);
Thomas Flori's avatar
Thomas Flori committed
        if (isset(self::$dependencies[$name])) {
            unset(self::$dependencies[$name]);
Thomas Flori's avatar
Thomas Flori committed
        }
    }

    /**
     * Checks if dependency $name is defined
     *
     * @param string $name
     * @return bool
     */
Thomas Flori's avatar
Thomas Flori committed
    public static function has($name)
    {
Thomas Flori's avatar
Thomas Flori committed
        return isset(self::$instances[$name]) || isset(self::$dependencies[$name]);
Thomas Flori's avatar
Thomas Flori committed
    private function __construct()
    {
    }