Контейнер зависимостей

Оглавление

1. Введение
2. Список методов
3. Примеры использования




Введение #
К оглавлению


ABC-фреймворк предоставляет собственный контейнер для внедрения зависимостей, основанный на анонимных функциях. Получить экземпляр контейнера можно, запросив обычный сервис:
1
2
3

   $container 
ABC::newService(ABC::CONTAINER); 




Либо расшаренный (сохраняющий состояние по принципу "синглтон"):
1
2
3

   $container 
ABC::sharedService(ABC::CONTAINER); 




Сервис контейнера предоставляет следующие публичные методы #
К оглавлению


1 set() Помещает зависимость в контейнер
2 setAsShared() Помещает в хранилище зависимость с общим доступом
3 get() Инициализирует и возвращает объект зависимости
4 getNew() Инициализирует и возвращает новый объект зависимости
5 checkService() Проверяет, есть ли сервис в контейнере
6 serviceSynthetic() Объявляет сервис синтетическим
7 injection() Внедряет один сервис в другой
8 unsetService() Удаляет сервис из хранилища




set() public method
К списку методов

Помещает зависимость в контейнер.

Этот метод записывает в хранилище анонимную функцию под уникальным идентификатором. В теле функции происходит инициализация классов зависимости.

Смотри еще setAsShared().

public Container::set ( $serviceId, $callable )
$serviceId string Идентификатор зависимости в контейнере.
$callable callable Анонимная функция.
return void




setAsShared() public method
К списку методов

Помещает в хранилище зависимость с общим доступом

Этот метод записывает в хранилище анонимную функцию под уникальным идентификатором по принципу "синглтон". В теле функции происходит инициализация классов зависимости.

Смотри еще set().

public Container::setAsShared ( $serviceId, $callable )
$serviceId string Идентификатор зависимости в контейнере.
$callable callable Анонимная функция.
return void




get() public method
К списку методов

Инициализирует и возвращает объект зависимости.

Находит по идентификатору и возвращает объект зависимости. Если сервис был упакован в контейнер, как shared, то возвращается один и тот же объект по принципу "синглтон". Если он упакован обычно, то каждый раз возвращается новый объект.

Смотри еще getNew().

public Container::get ( $serviceId )
$serviceId string Идентификатор зависимости в контейнере.
return object Объект зависимости




getNew() public method
К списку методов

Инициализирует и возвращает объект зависимости.

Возвращает по идентификатору сервиса новый объект, вне зависимости от того, как он был упакован.

Смотри еще get().

public Container::getNew ( $serviceId )
$serviceId string Идентификатор зависимости в контейнере.
return object Объект зависимости




checkService() public method
К списку методов

Проверяет, есть ли сервис в контейнере.

Возвращает булево значение в зависимости от того, есть ли в контейнере сервис с таким идентификатором.

public Container::checkService ( $serviceId )
$serviceId string Идентификатор зависимости в контейнере.
return boolean true, если есть, false, если нет.




serviceSynthetic() public method
К списку методов

Объявляет сервис синтетическим.

Если объявить сервис синтетическим, в него будет запрещено внедрение зависимости.

public Container::serviceSynthetic ( $serviceId )
$serviceId string Идентификатор зависимости в контейнере.
return void




injection() public method
К списку методов

Внедряет один сервис в другой по идентификаторам.

Выбирает по идентификатору из хранилища сервис и внедряет его как зависимость в другой через конструктор. Если передать третьим аргументом новый идентификатор, из первых двух будет организован новый сервис, который будет помещен в хранилище с этим идентификатором. Четвертым аргументом можно передать массив свойств, которые будут переданы в результирующий сервис. (См. примеры)

public Container::injection ( $serviceId, $dependenceId, $newService null, $property array )
$serviceId string Сервис-реципиент, в конструктор которого будет помещена зависимость.
$dependenceId string Идентификатор зависимости, которая будет помещена в реципиент.
$newService string Идентификатор нового сервиса, под которым можно получить реципиент с зависимостью.
$property string Массив свойств имя => значение.
return void




unsetService() public method
К списку методов

Удаляет сервис из хранилища.

Удалит по идентификатору все следы пребывания сервиса в хранилище. С этим методом нужна осторожность, неверное его использование может привести к непредсказуемым результатам.

public Container::unsetService ( $serviceId )
$serviceId string Идентификатор зависимости в контейнере.
return void




Примеры использования #
К оглавлению

Простая работа с зависимостью.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
<?php 

// Класс для проверки 
class MyClass 

    protected 
$time

    public function 
checkTime() 
    { 
        if (empty(
$this->time)) { 
            
$this->time microtime(true); 
        } 
         
        return 
$this->time
    } 

    
// Получаем сервис контейнера 
    
$container ABC::newService(ABC::CONTAINER); 

//////////////////////////////////////////////////////////////////     
//        ПРОСТОЙ ОБЪЕКТ 

    // Помещаем класс MyClass в контейнер в виде анонимной функции 
    
$container->set('MyClass',  
                    function() { 
                        return new 
MyClass
                    } 
            );  
             
    
// Так можно достать 
    
$obj $container->get('MyClass'); 
    echo 
$obj->checkTime();    // .....018.78 
    
echo '<br>'
    
sleep(1); 
    
// Это новый объект 
    
$obj $container->get('MyClass'); 
    echo 
$obj->checkTime(); // .....019.81 
    
echo '<br>'
     
//////////////////////////////////////////////////////////////////     
//     РАСШАРЕННЫЙ ОБЪЕКТ 
     
    // То же самое, но с общим доступом (под другим идентификатором)         
    
$container->setAsShared('Another',  
                            function() { 
                                return new 
MyClass
                            } 
            );     
     
     
    
// Так можно достать 
    
$obj $container->get('Another'); 
    echo 
$obj->checkTime();    // .....216.52 
    
echo '<br>'
    
sleep(1); 
    
// Теперь это синглтон 
    
$obj $container->get('Another'); 
    echo 
$obj->checkTime(); // .....216.52 
    
echo '<br>'




Внедрение зависимости в контейнере.

Классы для примера
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29

// Класс-реципиент
class Example1
{
    public 
$var;
    protected 
$dependence;
    
    public function 
__construct($dependence null)
    {
        if (
is_object($dependence)) {
            
$this->dependence $dependence;
        }
    }
    
    public function 
run()
    {
        
$this->dependence->display($this->var);
    }    
}

// Класс-зависимость
class Example2
{
    public function 
display($var)
    {
        echo 
$var;
    }
}




Простое внедрение зависимости через конструктор
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<?php 

    $container 
ABC::newService(ABC::CONTAINER); 
    
// Создаем первый сервис     
    
$container->set('service'
               function() { 
               return new 
Example1
               } 
           );  
    
// Затем второй   
    
$container->set('dependence'
               function() { 
               return new 
Example2
               } 
           );  
              
    
// Помещаем зависимость в сервис через конструктор 
    
$container->injection('service''dependence'); 
     
    
// Проверяем. 
    
$obj $container->get('service'); 
    
$obj->var 'test'
    
$obj->run(); // test 




Создание нового сервиса путем внедрения зависимости в исходный сервис.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25


    $container 
ABC::newService(ABC::CONTAINER); 

    
// Создаем первый сервис     
    
$container->set('service'
                       function() { 
                       return new 
Example1
                       } 
                   );  
    
// Затем второй   
    
$container->set('dependence'
                       function() { 
                       return new 
Example2
                       } 
                   );      
     
    
// Собираем третий сервис, поместив второй в первый 
    
$container->injection('service''dependence''newService'); 
     
    
// Вот так. 
    
$obj $container->get('newService'); 
    
$obj->var 'new test'
    
$obj->run(); // new test 




В таком случае первые два останутся неизменными.

Так же можно четвертым параметром передать значения для публичных свойств. Если не нужен третий сервис, то вместо него нужно поставить null. И тогда свойства будут переданы в сервис-реципиент.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30


    $container 
ABC::newService(ABC::CONTAINER); 
    
// Создаем первый сервис     
    
$container->set('service'
                       function() { 
                       return new 
Example1
                       } 
                   );  
    
// Затем второй   
    
$container->set('dependence'
                       function() { 
                       return new 
Example2
                       } 
                   );      
     
    
// Собираем третий сервис, поместив второй в первый, добавив свойства 
    
$container->injection('service''dependence''newService', ['var' => 'Hello, World!']); 
     
    
// Вот так. 
    
$obj $container->get('newService'); 
    
$obj->run(); // Hello, World! 
     
    // Или так, без третьего сервиса 
    
$container->injection('service''dependence'null, ['var' => 'Hello, World!']); 
     
    
// Свойства будут переданы в реципиент 
    
$obj $container->get('service'); 
    
$obj->run(); // Hello, World!   




После внедрения зависимости сервис в контейнере автоматически объявляется синтетическим. И дальнейшее внедрение в него запрещено.