phower/container

符合PSR-11容器的PHP依赖注入

1.0.0 2017-04-09 12:14 UTC

This package is auto-updated.

Last update: 2024-09-10 05:05:41 UTC


README

符合PSR-11容器的PHP依赖注入

要求

Phower Container 需要

  • PHP 5.6 或更高版本;建议使用 7.0 版本

实现

此包实现了

安装

使用Composer将Phower Container添加到任何PHP项目中

composer require phower/container

用法

在软件工程中,依赖注入是一种实现控制反转的软件设计模式,用于解决依赖关系。

依赖项是可以使用(服务)的对象。注入是将依赖项传递给需要使用它的依赖对象(客户端)的过程。

为了解决上述问题,我们可以使用一个容器,该容器知道如何将名称解析为实例。这样,我们只需将容器注入到我们的类中,然后只需请求它提供所需的依赖项。

实例

创建和使用容器非常简单

// in a bootstrap create the container and set a dependency
use Phower\Container\Container;

$container = new Container();
$container->set('some', new SomeClass());
$container->set('another', new AnotherClass());

// later inside our class aware of the container
if ($container->has('some') {
    /* @var $some SomeClass */
    $some = $container->get('some');
}

然而,如果您需要注册数百或数千个实例,这并不是非常高效,因为每次容器初始化时都会消耗太多时间和计算机资源。

条目

一种更有效的方法是简单地向容器中添加条目,然后在运行时解析到正确的实例

// in a bootstrap create the container and set a dependency
use Phower\Container\Container;

$container = new Container();
$container->add('some', 'SomeClass');
$container->add('another', 'AnotherClass');

// later inside our class aware of the container
if ($container->has('some') {
    /* @var $some SomeClass */
    $some = $container->get('some');
}

工厂

但如果我们的依赖项需要参数,这些参数也可能从容器内部获取怎么办?解决方案是注册一个工厂类而不是我们的最终类。

首先,让我们创建一个工厂类

use Phower\Container\FactoryInterface;
use Phower\Container\ContainerInterface;

class SomeFactory implments FactoryInterface
{
    public function create(ContainerInterface $container)
    {
        $arg1 = 123;
        $arg2 = $container->get('arg2');
        return new SomeClass($arg1, $arg2);
    }
}

请注意,您的工厂必须始终实现 Phower\Container\FactoryInterface

然后,在容器上注册工厂和所需的参数

// in a bootstrap create the container and set a dependency
use Phower\Container\Container;

$container = new Container();
$container->add('arg2', 'AnotherClass');
$container->addFactory('some', 'SomeFactory');

// later inside our class aware of the container
if ($container->has('some') {
    /* @var $some SomeClass */
    $some = $container->get('some');
}

抽象工厂

从容器中获取依赖项的另一种方法是使用抽象(动态)工厂。这样,您可以基于名称模式或命名空间实例化依赖项。

假设您在命名空间 'Some' 下有许多类

  • Some\OneClass
  • Some\OtherClass
  • Some\ThirdClass

我们不需要单独注册它们,只需要一个抽象工厂即可

use Phower\Container\AbstractFactoryInterface;
use Phower\Container\ContainerInterface;

class SomeAbstractFactory implments AbstractFactoryInterface
{
    public function canCreate(ContainerInterface $container, $name)
    {
        return substr($name, 0, 5) === 'Some\\';
    }

    public function create(ContainerInterface $container, $name)
    {
        return new $name();
    }
}

请注意,您的抽象工厂必须始终实现 Phower\Container\AbstractFactoryInterface

然后,在容器上注册抽象工厂

// in a bootstrap create the container and set a dependency
use Phower\Container\Container;

$container = new Container();
$container->addAbstractFactory('some', 'SomeAbstractFactory');

// later inside our class aware of the container

/* @var $one Some\OneClass */
$one = $container->get('Some\OneClass');

/* @var $other Some\OtherClass */
$other = $container->get('Some\OtherClass');

/* @var $third Some\ThirdClass */
$third = $container->get('Some\ThirdClass ');

别名

有时您可能需要在容器中对同一条目使用不同的名称。这可以通过添加别名而不是复制引用来实现

// in a bootstrap create the container and set a dependency
use Phower\Container\Container;

$container = new Container();
$container->add('some', 'SomeClass');
$container->addAlias('something', 'some');

// later inside our class aware of the container
if ($container->has('something') {
    /* @var $something SomeClass */
    $something = $container->get('something');
}

从配置创建容器

大多数情况下,最好从(巨大的)配置数组创建容器。这可以通过使用带有条目数组的静态 create 方法来完成

// in a bootstrap create the container and set a dependency
use Phower\Container\Container;

$container = Container::create([
    'classes' => [
        'some' => 'SomeClass',
        // more classes ...
    ],
    'factories' => [
        'some-factory' => 'SomeFactory',
        // more factories ...
    ],
    'abstract_factories' => [
        'abstract-factory' => 'SomeAbstractFactory',
        // more abstract factories ...
    ],
    'aliases' => [
        'alis-to-some' => 'some',
        // more aliases ...
    ],
]);

运行测试

测试可用在单独的命名空间中,可以在命令行中使用 PHPUnit 运行

vendor/bin/phpunit

编码标准

Phower 代码按照 PSR-2 编码风格标准编写。为了强制执行这一点,还提供了 CodeSniffer 工具,并可以运行如下

vendor/bin/phpcs

报告问题

如果您发现此代码有问题,请在GitHub Issues中创建一个工单,地址为:https://github.com/phower/container/issues

贡献者

开源是由贡献构成的。如果您想为Phower做出贡献,请按照以下步骤操作

  1. 将最新版本分叉到您自己的仓库中。
  2. 编写您的更改或添加,并提交。
  3. 遵循PSR-2编码风格标准。
  4. 确保您对更改有完整的单元测试覆盖。
  5. 前往GitHub Pull Requests页面:https://github.com/phower/container/pulls 创建新的请求。

谢谢!

更改和版本控制

此代码的所有相关更改都记录在单独的日志文件中。

版本号遵循语义化版本的建议。

许可证

Phower代码在MIT许可证下维护。