1
\$\begingroup\$

I'm currently creating my own microframework for learning purpose and I want to make it more powerful by providing a way to register classes and instantiate them (once) only when needed. So here is my try :

<?php


namespace Framework\Core;

use Exception;
use ReflectionClass;

/**
 * Class Container
 *
 * @package App\Core
 *
 * Depandancies injection and lazy loading, I guess ? (not sure how to call it for now)
 *
 */
class Container
{

    /**
     * @var array Contains all classes instance.
     */
    private static $instances = array();

    /**
     * @var array Contains all fully qualified classes name.
     */
    private static $classes = array();

    /**
     * @var string Should contain the name of the last registered class name.
     */
    private static $lastRegistered;

    /**
     * Container constructor.
     */
    private function __construct() {}

    /**
     * Prevents cloning.
     */
    private function __clone() {}

    /**
     * Prevents deserialization.
     */
    private function __wakeup() {}

    /**
     * Gets a class instance.
     *
     * @param $name
     * @param null $renew
     * @return mixed
     * @throws Exception
     */
    public static function get($name = NULL) {
        $name = (!$name) ? self::$lastRegistered : $name;
        if (self::$classes[$name]) {
            if (self::$instances[$name]) {
                return self::$instances[$name];
            } else {
                self::$instances[$name] = new self::$classes[$name];
                return self::$instances[$name];
            }
        } else {
            throw new Exception('The following class name could not be found: ' . $name);
        }
    }

    /**
     * Registers a class.
     *
     * @param $name
     * @param $class
     * @return $this|null
     * @throws Exception
     */
    public static function register($name, $class) {
        $reflection = new ReflectionClass($class);
        if (!$reflection->isInstantiable()) {
            throw new Exception('The provided class is not instantiable: ' . $class);
        }
        if (!in_array($name, self::$classes)) {
            self::$classes[$name] = $class;
        }
        self::$lastRegistered = $name;
        return __CLASS__;
    }

    /**
     * Returns an array of all registered classes.
     *
     * @return array
     */
    public static function getRegisteredClasses() {
        return self::$classes;
    }

    /**
     * Returns an array of all instantiated classes.
     *
     * @return array
     */
    public static function getInstantiatedClasses() {
        return self::$instances;
    }

}

So basically, what it does it that it allows you to register a class name as follow :

Container::register('config', \Framework\Core\Config::class);

And then you can get the class instance like this :

Container::get('config');

You can also register() and immediately get() the class instance like this :

Container::register('config', \Framework\Core\Config::class)::get();

I added this "feature" into my microframework in order to prevent instantiating a class more than one time.

The interesting part is that it instantiates the class only when you call the get() method, not when you register it. It allows me to register all framework dependancies at once when the app starts and then get their instances later.

Obvisouly, this class needs improvement in terms of "options". Because, what if I need to register() and get() a class that needs arguments to be passed into its constructor ? I'm aware about that and before making this class more "flexible" I just wanted to know if it's useful to have a "feature" like this in my microframework.


My question is : How is this called ? Singleton ? Container ? Dependency injection ?
Also, can my microframework benefits from having this "feature" ?

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.