4.5. Definition extensions and overriding

未匹配的标注

定义扩展和覆盖

一个简单的应用程序通常使用一个或两个定义源:自动装配 (或注解) + 定义文件/数组。

但是,在更复杂的应用程序或模块化系统中,您可能希望拥有多个定义文件 (例如:每个模块/插件/…都有其定义文件)。在这种情况下,PHP-DI提供了一个清晰而强大的系统来重写/扩展定义

定义源的优先级

从最低优先级到最高优先级:

  • 自动装配(如果启用)
  • 注解(如果启用)
  • PHP definitions (文件或数组)中定义的顺序
  • 使用 $container->set()在容器中直接添加定义

示例

class Foo
{
    public function __construct(Bar $param1)
    {
    }
}

PHP-DI 会使用自动装配注入 Bar实例,因为注解有更高的优先级,因此我们可以使用注解进行覆盖:

class Foo
{
    /**
     * @Inject({"my.specific.service"})
     */
    public function __construct(Bar $param1)
    {
    }
}

通过使用基于文件的定义来覆盖注解和自动装配,可以让系统更加灵活:

return [
    'Foo' => DI\create()
        ->constructor(DI\get('another.specific.service')),
    // ...
];

如果有另一个定义文件(在此之后注册),则可以再次覆盖该定义。

扩展定义

对象

DI\create() 会完全覆盖以前所有的定义,甚至是自动装配。它不允许扩展另一个定义。如果要这样做,请参见下面的“装饰器”部分。

如果使用自动装配(或注解)构建对象,则可以使用DI \ autowire()覆盖特定参数:

class Foo
{
    public function __construct(Bar $param1, $param2)
    {
    }
}

return [
    Foo::class => DI\autowire()
        ->constructorParameter('param2', 'Hello!'),
];

在此示例中, 我们扩展了自动装配定义以设置 $param2 ,因为它无法通过自动装配猜测注入(无类型提示)。$ param1则不受影响,并且已自动注入。

请注意, DI\autowire(), 与 DI\create()一样, 不允许扩展定义。它仅允许自定义自动装配的完成方式。在下面的示例中,第二个定义将完全覆盖第一个定义:

return [
    Database::class => DI\autowire()
        ->constructorParameter('host', '192.168.34.121'),
];
return [
    Database::class => DI\autowire()
        ->constructorParameter('port', 3306),
];

数组

你可以使用DI\add()将条目添加到另一个文件/数组定义的阵列中:

return [
    'array' => [
        DI\get(Entry::class),
    ],
];
return [
    'array' => DI\add([
        DI\get(NewEntry::class),
    ]),
];

解析后,array将包含2个条目。 如果您忘记使用DI \ add(),则前面array的值将被完全覆盖!

请注意,即使之前未声明array,也可以使用DI \ add()

装饰器

您可以使用DI \ decorate()装饰对象:

return [
    ProductRepository::class => function () {
        return new DatabaseRepository();
    },
];
return [
    ProductRepository::class => DI\decorate(function ($previous, ContainerInterface $c) {
         //将数据库仓库包装在缓存代理中
        return new CachedRepository($previous);
    }),
];

可调用对象的第一个参数是先前定义返回的实例(即我们要修饰的实例),第二个参数是容器。

您可以对任何先前的定义(工厂,对象,值,环境变量等)使用DI \ decorate()

本文章首发在 LearnKu.com 网站上。

本译文仅用于学习和交流目的,转载请务必注明文章译者、出处、和本文链接
我们的翻译工作遵照 CC 协议,如果我们的工作有侵犯到您的权益,请及时联系我们。

原文地址:https://learnku.com/docs/php-di/6.0/defi...

译文地址:https://learnku.com/docs/php-di/6.0/defi...

上一篇 下一篇
贡献者:2
讨论数量: 0
发起讨论 只看当前版本


暂无话题~