Pull to refresh

Syringe — декларативный IoC Container на PHP

Reading time3 min
Views7.1K
Инверсия управления (Inversion of Control) — важный принцип объектно-ориентированного программирования, используемый для уменьшения связанности в компьютерных программах (“Википедия”).

Простой как Pimple, мощный как Symfony DI


Syringe — простой IoC Container написанный на PHP с большим количеством возможностей и декларативной конфигурацией.

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

Далее возможности расписаны более подробно.

Первый пример


Есть класс Foo. Его конструктор принимает два параметра:

<?php

class Foo
{
    protected $a;
    protected $b;

    public function __construct($a, $b)
    {
        $this->a = $a;
        $this->b = $b;
    }
}


Описание сервиса в конфигурации выглядит так:

services:
  foo: 
    class:     'Foo',
    arguments: ['value1', 'value2']


Теперь при запросе сервиса foo, будет создан экземпляр класса Foo.

<?php

// container init...

$foo = $container->get('foo'); // Foo


Внедрение Doctrine


Более сложный пример описывает использование Doctrine в проекте.

Классу Foo требуется соединение с базой данных для своей работы:

<?php

class Foo
{
    protected $connection;

    public function __construct($connection)
    {
        $this->connection = $connection;
    }
    
    // ...
}


Конфигурация приложения будет выглядеть так:

# параметры доктрины
doctrine.configuration_paths: ['config/doctrine']
doctrine.db_parameters:
  driver: 'pdo_mysql'
  user: 'root'
  password: '1234'
  dbname: 'game'
  charset: 'UTF8'

services:
# сервис foo
  foo:
    class: 'Foo'
    arguments: ['@db_connection']

# сервисы доктрины
  doctrine.setup_configuration:
    factoryStaticMethod:
      - 'Doctrine\ORM\Tools\Setup'
      - 'createAnnotationMetadataConfiguration'
    arguments:
      - '%doctrine.configuration_paths%'

  doctrine.entity_manager:
    factoryStaticMethod:
      - 'Doctrine\ORM\EntityManager'
      - 'create'
    arguments:
      - '%doctrine.db_parameters%'
      - '@doctrine.setup_configuration'
    alias: doctrine

  doctrine.connection:
    factoryMethod:
      - '@doctrine.entity_manager'
      - 'getConnection'
    alias: db_connection


При запросе сервиса foo в аргументы конструктора будет передано соединение с базой данных:

<?php

// init container ...

$foo = $container->get('foo');


Исходники: SyringeExampleDoctrine

Внедрение тега


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

В примере используется консольное приложение на основе Symfony Console Component:

services:
  app:
    class: 'Symfony\Component\Console\Application'
    calls:
      - ['addCommands', ['#console_commands']]

  command.foo:
    class: 'Command\FooCommand'
    tags: console_commands
  command.bar:
    class: 'Command\BarCommand'
    tags: console_commands


Сервисы, помеченные тегом console_commands, попадут списком в качестве аргумента функции addCommands.

Исходники: SyringeExampleConsole

Принцип работы


Конфигурация контейнера задается при помощи yaml, json или php формата.
При компиляции происходит процесс конвертирования конфигурации в массив php. Сконвертированная конфигурация экспортируется в файл, который используется для запуска контейнера.

Алгоритм компиляции следующий:
  1. конвертирование из внешнего формата (например yaml) в массив php,
  2. добавление конфигурации в Builder,
  3. разрешение зависимостей от параметров (%parameter.name%),
  4. отделение параметров от конфигурации сервисов,
  5. валидация и распределение конфигурации по коллекторам,
  6. слияние конфигурации из коллекторов и параметров.


После этого контейнер готов к работе.

Будущее


Конечно Syringe не вытеснит реализации DI из Symfony 2 или Zend2 — они предоставляют такую же функциональность и тесно интегрированы с фреймворками.

Однако цель его — не в этом. Его ниша — там, где нет топовых фреймворков. Он рассчитан на проекты без встроенного IoC Container и новые легкие приложения, где его еще только предстоит выбрать. И здесь он даст фору другим библиотекам, обгоняя их по функциональности и удобству.

Официальный сайт проекта: http://butterfly.pro/components/dependency-injection

Буду очень рад Вашим комментариям и предложениям!

UPD: в связи с развитием проект был переименован в Butterfly, а Syringe IoC Container стал одним из его компонентов.
Tags:
Hubs:
Total votes 19: ↑13 and ↓6+7
Comments7

Articles