定制 fi1a/dependency-injection 二次开发

按需修改功能、优化性能、对接业务系统,提供一站式技术支持

邮箱:yvsm@zunyunkeji.com | QQ:316430983 | 微信:yvsm316

fi1a/dependency-injection

最新稳定版本:1.0.2

Composer 安装命令:

composer require fi1a/dependency-injection

包简介

Dependency injection container

README 文档

README

Latest Version Software License PHP Version Coverage Status Total Downloads Support mail

Контейнер dependency injection, может разрешать зависимости, создавать экземпляры и настраивать классы. Поддерживает внедрение конструктора, свойств и методов.

Установка

Установить этот пакет можно как зависимость, используя Composer.

composer require fi1a/dependency-injection

Использование контейнера

Для использования контейнера dependency injection, сначала необходимо в конфигурацию задать определения созданное с помощью builder'а. Название определения обычно является именем интерфейса. Когда запрашивается тип для создания объекта, будет использоваться это определение. Это происходит при вызове метода get непосредственно из контейнера. Объекты также создаются не явно при разрешении зависимостей.

use Fi1a\DI\Container;
use Fi1a\DI\ContainerConfig;
use Fi1a\DI\Builder;
use Fi1a\Unit\DI\Fixtures\ClassA;
use Fi1a\Unit\DI\Fixtures\ClassAInterface;
use Fi1a\Unit\DI\Fixtures\ClassC;
use Fi1a\Unit\DI\Fixtures\ClassCInterface;

$config = new ContainerConfig();

$config->addDefinition(
    Builder::build(ClassAInterface::class)
        ->defineClass(ClassA::class)
        ->getDefinition()
);

$config->addDefinition(
    Builder::build(ClassCInterface::class)
        ->defineClass(ClassC::class)
        ->defineConstructor([1, true])
        ->getDefinition()
);

$container = new Container($config);

$container->get(ClassCInterface::class); // ClassCInterface

Объект может быть определен несколькими способами:

  • defineClass - сопоставление с конкретным классом;
  • defineFactory - если реализация сложная и может быть лучше описана в коде, то следует использовать фабричный метод. При использовании фабричного метода, зависимости в аргументах автоматически разрешаются.
  • defineObject - вернуть созданный экземпляр объекта.

Также доступны следующие определения:

  • defineConstructor - задает аргументы для конструктора класса определенного как defineClass;
  • defineProperty - задает значение свойства объекта;
  • defineProperties - задает ассоциативный массив со значениями свойств объекта;
  • defineMethod - задает метод объекта, который необходимо вызвать с объявленными аргументами;
  • defineMethods - задает ассоциативный массив с методами объекта, которые необходимо вызвать с объявленными аргументами.

При отсутствии определения для запрашиваемого типа, контейнер выбросит исключение Fi1a\DI\Exceptions\NotFoundException.

defineClass

Сопоставление с конкретным классом, определение аргументов конструктора, задание свойств и вызов методов:

use Fi1a\DI\Container;
use Fi1a\DI\ContainerConfig;
use Fi1a\DI\Builder;
use Fi1a\Unit\DI\Fixtures\ClassA;
use Fi1a\Unit\DI\Fixtures\ClassAInterface;

$config = new ContainerConfig();

$config->addDefinition(
    Builder::build(ClassAInterface::class)
        ->defineClass(ClassA::class)
        ->defineConstructor([
            'parameter1' => 10,
        ])
        ->defineProperty('property1', 100)
        ->defineMethod('setProperty2', [true])
        ->getDefinition()
);

$container = new Container($config);

/** @var ClassA $object */
$object = $container->get(ClassAInterface::class); // ClassAInterface

$object->property1; // 100
$object->property2; // true

defineFactory

Используется замыкание как фабричный метод:

use Fi1a\DI\Container;
use Fi1a\DI\ContainerConfig;
use Fi1a\DI\Builder;
use Fi1a\Unit\DI\Fixtures\ClassA;
use Fi1a\Unit\DI\Fixtures\ClassAInterface;
use Fi1a\Unit\DI\Fixtures\ClassB;

$config = new ContainerConfig();

$config->addDefinition(
    Builder::build(ClassAInterface::class)
        ->defineFactory(function (ClassB $classB) {
            $instance = new ClassA($classB);
            $instance->property1 = 100;
            $instance->property2 = true;

            return $instance;
        })
        ->getDefinition()
);

$container = new Container($config);

/** @var ClassA $object */
$object = $container->get(ClassAInterface::class); // ClassAInterface

$object->property1; // 100
$object->property2; // true

Использование фабричного метода в классе:

use Fi1a\DI\Container;
use Fi1a\DI\ContainerConfig;
use Fi1a\DI\Builder;
use Fi1a\Unit\DI\Fixtures\ClassA;
use Fi1a\Unit\DI\Fixtures\ClassAInterface;
use Fi1a\Unit\DI\Fixtures\FactoryA;

$config = new ContainerConfig();

$config->addDefinition(
    Builder::build(ClassAInterface::class)
        ->defineFactory([FactoryA::class, 'factoryStatic'])
        ->getDefinition()
);

$container = new Container($config);

/** @var ClassA $object */
$object = $container->get(ClassAInterface::class); // ClassAInterface

$object->property1; // 100
$object->property2; // true

defineObject

Использовать уже созданный экземпляр объекта:

use Fi1a\DI\Container;
use Fi1a\DI\ContainerConfig;
use Fi1a\DI\Builder;
use Fi1a\Unit\DI\Fixtures\ClassB;
use Fi1a\Unit\DI\Fixtures\ClassBInterface;

$config = new ContainerConfig();

$config->addDefinition(
    Builder::build(ClassBInterface::class)
        ->defineObject(new ClassB())
        ->getDefinition()
);

$container = new Container($config);

/** @var ClassB $object */
$object = $container->get(ClassBInterface::class); // ClassBInterface

Хелпер di

Доступен хелпер di(), возвращающий один экземпляр контейнера для регистрации опредлений в других пакетах.

use Fi1a\DI\Builder;
use Fi1a\Unit\DI\Fixtures\ClassA;
use Fi1a\Unit\DI\Fixtures\ClassAInterface;
use Fi1a\Unit\DI\Fixtures\ClassC;
use Fi1a\Unit\DI\Fixtures\ClassCInterface;

di()->config()->addDefinition(
    Builder::build(ClassAInterface::class)
        ->defineClass(ClassA::class)
        ->getDefinition()
);

di()->config()->addDefinition(
    Builder::build(ClassCInterface::class)
        ->defineClass(ClassC::class)
        ->defineConstructor([1, true])
        ->getDefinition()
);

di()->get(ClassCInterface::class); // ClassCInterface

Создание определения из массива

Для создания определения из массива можно воспользоваться методом buildFromArray класса реализующего интерфейс Fi1a\DI\ArrayBuilderInterface:

use Fi1a\DI\ArrayBuilder;
use Fi1a\DI\Container;
use Fi1a\DI\ContainerConfig;
use Fi1a\Unit\DI\Fixtures\ClassA;
use Fi1a\Unit\DI\Fixtures\ClassAInterface;

$config = new ContainerConfig();

$config->addDefinition(
    $definition = ArrayBuilder::buildFromArray([
        'name' => ClassAInterface::class,
        'class_name' => ClassA::class,
        'constructor' => [100, true],
        'properties' => [
            'property1' => 100,
            'property2' => true,
        ],
        'methods' => [
            'setProperty1' => [100],
            'setProperty2' => [true],
        ],
    ])->getDefinition()
);

$container = new Container($config);

/** @var ClassA $object */
$object = $container->get(ClassAInterface::class); // ClassAInterface

Преобразование определения и коллекций в массив

Для преобразования определений и коллекций в массив, можно воспользоваться методом definition, или collection класса реализующего интерфейс Fi1a\DI\ToArrayInterface:

use Fi1a\DI\ContainerConfig;
use Fi1a\DI\Builder;
use Fi1a\DI\ToArray;
use Fi1a\Unit\DI\Fixtures\ClassA;
use Fi1a\Unit\DI\Fixtures\ClassAInterface;

$config = new ContainerConfig();

$definition = Builder::build(ClassAInterface::class)
    ->defineClass(ClassA::class)
    ->defineConstructor([
        'parameter1' => 10,
    ])
    ->defineProperty('property1', 100)
    ->defineMethod('setProperty2', [true])
    ->getDefinition();

$config->addDefinition($definition);

$toArray = new ToArray();

$array = $toArray->collection($config->getDefinitions()); // [[...], [...]]
$arrayDefinition = $toArray->definition($definition); // [...]

统计信息

  • 总下载量: 2.39k
  • 月度下载量: 0
  • 日度下载量: 0
  • 收藏数: 0
  • 点击次数: 0
  • 依赖项目数: 6
  • 推荐数: 0

GitHub 信息

  • Stars: 0
  • Watchers: 1
  • Forks: 0
  • 开发语言: PHP

其他信息

  • 授权协议: MIT
  • 更新时间: 2022-12-29

承接程序开发

PHP开发

VUE

Vue开发

前端开发

小程序开发

公众号开发

系统定制

数据库设计

云部署

网站建设

安全加固