Простой контейнер


Я строю веб-приложения и пытается сделать мой многоразовый код. Я решил создать компоненты, которые могут быть использованы вне этого проекта.

Сейчас я пытаюсь создать простой контейнер, один класс, и я хотел бы помочь проверить его. Я думаю сделать что-то вроде этого:

class Container
{
    protected static $_services = array();

    protected static $_shared = array();

    /**
     * Create and store a new service in the container.
     *
     * @param   string  $service  Service identifier name.
     * @param   mixed   $params   Service parameters, array or a Closure object.
     * @return  object            Ramverk\Framework\Container.
     */
    public function add($service, $params)
    {
        if (!is_object($params) && !is_array($params)) {
            throw new Exception("Service params must be a Closure object or an array.");
        }

        static::$_services[$service] = $params;
        return $this;
    }

    /**
     * Get a shared service object, will return the same object each time.
     *
     * @param   string  $service  Name of the shared service to get.
     * @return  object            Shared service object.
     */
    public function get($service)
    {
        if (!array_key_exists($service, static::$_shared)) {
            static::$_shared[$service] = $this->getNew($service);
        }

        return static::$_shared[$service];
    }

    /**
     * Get a new instance of an existing service.
     *
     * @param   string  $service  Name of the service to create.
     * @return  object            Create service object.
     */
    public function getNew($service)
    {
        // Make sure service has been added
        if (!array_key_exists($service, static::$_services)) {
            throw new Exception("Service '$service' not found");
        }

        // get container service
        $container = static::$_services[$service];

        // If service is wrapped in a Closure we invoke it
        if (is_object($container)) {
            return $container();
        }

        // Make sure we have a class to work with
        if (!isset($container['class'])) {
            throw new Exception("A class must be set in $service service");
        }

        // Get service key and remove key
        $class = $container['class'];
        unset($container['class']);

        // Check if this service uses adapters
        if (array_key_exists('adapter', $container)) {
            $config = (array) $container['adapter'];
            if (!isset($config['class'])) {
                throw new Exception("An adapter class must be set in $service service");
            }

            // Grab adapter name and remove unwanted the keys
            $adapter = $config['class'];
            unset($config['class'], $container['adapter']);

            // Create the instance and return it
            return new $class(new $adapter($config));
        }

        // Create class instance and pass parameters to constructor
        return new $class($container);
    }
}

Добавление нового сервиса должно содержать имя (идентификатор) и закрытие объекта или массива. Следующие создаст и возвратит то же самое:

$container = new Container();
$container->add('session', function() {
    $config = array(
        'name' => 'my_session',
        'expires' => '4 hours',
    );
    $storage = new Session\Adapter\Native($config);
    return new Session($storage);
});

// - Equals to:

$container->add('session', array(
    'class' => 'Session',
    'adapter' => array(
        'class' => 'Session\Adapter\Native',
        'name' => 'my_session',
        'expires' => '4 hours',
    ),
));


// Now I get the shared object with:
$session = $container->get('session');

// Or create a new instance
$session = $container->getNew('session');

Я все правильно делаю?



2232
5
задан 30 июня 2011 в 07:06 Источник Поделиться
Комментарии
3 ответа

Почему ты определение свойства как статическое? Я бы совершенно не делать. Это означает, двух экземпляров контейнера будет иметь те же услуги.

6
ответ дан 7 октября 2011 в 08:10 Источник Поделиться

Я думаю, что прыщик ( http://pimple-project.org/ ) это версия используется в Symfony 2.
может быть стоит проверить.

3
ответ дан 8 августа 2011 в 03:08 Источник Поделиться

Вы должны прочитать этот цикл статей: http://fabien.potencier.org/article/11/what-is-dependency-injection

Кроме того, результирующая составляющая (для PHP 5.2+) есть: http://components.symfony-project.org/dependency-injection/

1
ответ дан 30 июня 2011 в 09:06 Источник Поделиться