文档/容器/集装箱结构

容器

HLEB2 框架中,容器 是一个所谓的 服务 集合,可以从中获取服务或将服务添加到容器中。
服务是逻辑上自包含的结构,用于特定目的。

HLEB2 框架中,容器中的服务初始化过程被简化,没有不必要的抽象。
服务并不是通过框架从配置中初始化的,而是在一个特殊的类 App\Bootstrap\BaseContainer 中,该类可以被使用框架的开发者编辑。 (大多数情况下,您会使用 App\Bootstrap\ContainerFactory 类,因为在该类中将服务定义为 单例。)
这些类的所有文件都位于项目的 /app/Bootstrap/ 目录中。

通过这种结构,可以在容器中添加大量服务,而不会显著影响性能。


#BaseContainer 类

该类表示将用于获取服务的容器。

如果每次从容器中请求服务时都需要新建一个该类的实例,则应在这里通过 match() 表达式指定。

<?php
// File /app/Bootstrap/BaseContainer.php

namespace App\Bootstrap;

use 
Hleb\Constructor\Containers\CoreContainer;

final class 
BaseContainer extends CoreContainer implements ContainerInterface
{
    #[\Override]
    final public function 
get(string $id): mixed
    
{
        return 
ContainerFactory::getSingleton($id) ?? match ($id) {

            
// ... //

            
default => parent::get($id),
        };
    }
}

添加服务的方式类似于在 ContainerFactory 类中添加服务的方式。


#ContainerFactory 类

一个用于创建服务的 单例 工厂,并具备覆盖框架默认服务的功能。 用于添加自定义服务,这些服务仅在每个请求中初始化一次。

例如,可能需要添加一个 RequestIdService,它返回当前请求的唯一 ID。 这是一个演示服务示例,通常服务表示更复杂的结构。 将其创建添加到 ContainerFactory 类中:

<?php
// File /app/Bootstrap/ContainerFactory.php

namespace App\Bootstrap;

use 
App\Bootstrap\Services\RequestIdService;
use 
App\Bootstrap\Services\RequestIdInterface;
use 
Hleb\Constructor\Containers\BaseContainerFactory;

final class 
ContainerFactory extends BaseContainerFactory
{
    public static function 
getSingleton(string $id): mixed
    
{
        
self::has($id) or self::$singletons[$id] = match ($id) {

            
// New service controller.
            
RequestIdInterface::class => new RequestIdService(),

            default => 
null
        
};
        return 
self::$singletons[$id];
    }

    #[\Override]
    public static function 
rollback(): void
    
{
        
self::$singletons = [];
    }
}

现在,当从容器中请求 RequestIdInterface 时,它将返回一个作为 单例RequestIdService 实例。
获取的键不仅可以定义为接口,还可以是基础类 RequestIdService,在 DI(依赖注入)中将以这种方式使用。

尽管 match() 表达式可以包含多个键指向一个值,但为了避免服务重复(从而违反 singleton 原则),应只分配一个。


#在容器中创建方法

为了简化使用键为 RequestIdInterface 的新服务的工作,让我们在容器中添加一个新方法。这将使通过 IDE 在容器中更容易找到它。
新方法 requestId 被添加到容器类 (BaseContainer)。现在该类看起来如下所示:

<?php
// File /app/Bootstrap/BaseContainer.php

namespace App\Bootstrap;

use 
App\Bootstrap\Services\RequestIdInterface;
use 
Hleb\Constructor\Containers\CoreContainer;

final class 
BaseContainer extends CoreContainer implements ContainerInterface
{
    #[\Override]
    final public function 
get(string $id): mixed
    
{
        return 
ContainerFactory::getSingleton($id) ?? match ($id) {

            
// ... //

            
default => parent::get($id),
        };
    }

    
// New method.
    
#[\Override]
    final public function 
requestId(): RequestIdInterface
    
{
        return 
$this->get(RequestIdInterface::class);
    }
}

重要!为了使其工作,requestId 方法还必须添加到 App\Bootstrap\ContainerInterface 接口中。

在示例中,服务通过接口分配,这允许容器中的服务类发生变化,同时保持对接口的绑定。 对于您自己的应用程序内部类,您也可以在此省略接口,并直接指定类映射。

对于框架的标准服务,这些操作都已经完成;您可以通过相应的控制器方法获取它们。

新服务的创建过程详见添加 实际库的示例。

创建互相依赖的服务在 非标准容器使用 一节中描述。


#容器的 rollback() 函数

您可能已经注意到 ContainerFactory 类中的 rollback() 函数。 该函数对于在框架的异步使用期间重置服务状态是必需的,例如,当与 RoadRunner 一起使用时。

其工作原理如下:
当框架完成异步请求时,它会重置标准服务的状态。
然后,它调用 rollback() 函数,以执行其中包含的代码以重置手动添加的服务的状态。

因此,如果在异步模式下使用框架,您可以在此初始化服务状态重置(以及任何其他模块的重置)。

控制台命令 使用容器

页面翻译:chatgpt 4-o
返回顶部