hyperf/doc/zh/component-guide/configprovider.md
狂奔的蚂蚁 305772d84d
文档错别字修改
文档错别字修改
2019-09-03 10:36:57 +08:00

4.9 KiB
Raw Blame History

ConfigProvider 机制

ConfigProvider 机制对于 Hyperf 组件化来说是个非常重要的机制,组件间的解耦组件的独立性 以及 组件的可重用性 都是基于这个机制才得以实现。

什么是 ConfigProvider 机制

简单来说,就是每个组件都会提供一个 ConfigProvider,通常是在组件的根目录提供一个 ConfigProvider 的类,ConfigProvider 会提供对应组件的所有配置信息,这些信息都会被 Hyperf 框架在启动时加载,最终ConfigProvider 内的配置信息会被合并到 Hyperf\Contract\ConfigInterface 对应的实现类去,而 dependencies 信息则会合并到 Hyperf\Di\Definition\DefinitionSource 去,从而实现该组件在 Hyperf 框架下使用时要进行的配置初始化。

ConfigProvider 本身不具备任何依赖,不继承任何的抽象类和不要求实现任何的接口,只需提供一个 __invoke 方法并返回一个对应配置结构的数组即可。

如何定义一个 ConfigProvider

通常来说,ConfigProvider 会定义在组件的根目录下,一个 ConfigProvider 类通常如下:

<?php

namespace Hyperf\Foo;

class ConfigProvider
{
    public function __invoke(): array
    {
        return [
            // 合并到  config/dependencies.php 文件
            'dependencies' => [],
            // 合并到  config/autoload/annotations.php 文件
            'scan' => [
                'paths' => [
                    __DIR__,
                ],
            ],
            // 默认 Command 的定义,合并到 Hyperf\Contract\ConfigInterface 内,换个方式理解也就是与 config/autoload/commands.php 对应
            'commands' => [],
            // 与 commands 类似
            'listeners' => [],
        ];
    }
}

只创建一个类并不会被 Hyperf 自动的加载,您仍需在组件的 composer.json 添加一些定义,告诉 Hyperf 这是一个 ConfigProvider 类需要被加载,您需要在组件内的 composer.json 文件内增加 extra.hyperf.config 配置,并指定对应的 ConfigProvider 类的命名空间,如下所示:

{
    "name": "hyperf/foo",
    "require": {
        "php": ">=7.2"
    },
    "autoload": {
        "psr-4": {
            "Hyperf\\Foo\\": "src/"
        }
    },
    "extra": {
        "hyperf": {
            "config": "Hyperf\\Foo\\ConfigProvider"
        }
    }
}

定义了之后需执行 composer installcomposer updatecomposer dump-autoload 等会让 Composer 重新生成 composer.lock 文件的命令,才能被正常读取。

ConfigProvider 机制的执行流程

关于 ConfigProvider 的配置并非一定就是这样去划分,这是一些约定成俗的格式,实际上最终如何来解析这些配置的决定权也在于用户,用户可通过修改 Skeleton 项目的 config/container.php 文件内的代码来调整相关的加载,也就意味着,config/container.php 文件决定了 ConfigProvider 的扫描和加载。

组件设计规范

由于 composer.json 内的 extra 属性在数据不被利用时无其它作用和影响,故这些组件内的定义在其它框架使用时,不会造成任何的干扰和影响,顾 ConfigProvider 是一种仅作用于 Hyperf 框架的机制,对其它没有利用此机制的框架不会造成任何的影响,这也就为组件的复用打下了基础,但这也要求在进行组件设计时,必须遵循以下规范:

  • 所有类的设计都必须允许通过标准 OOP 的使用方式来使用,所有 Hyperf 专有的功能必须作为增强功能并以单独的类来提供,也就意味着在非 Hyperf 框架下仍能通过标准的手段来实现组件的使用;
  • 组件的依赖设计如果可满足 PSR 标准 则优先满足且依赖对应的接口而不是实现类;如 PSR 标准 没有包含的功能,则可满足由 Hyperf 定义的契约库 Hyperf/contract 内的接口时优先满足且依赖对应的接口而不是实现类;
  • 对于实现 Hyperf 专有功能所增加的增强功能类,通常来说也会对 Hyperf 的一些组件有依赖,那么这些组件的依赖不应该写在 composer.jsonrequire 项,而是写在 suggust 项作为建议项存在;
  • 组件设计时不应该通过注解进行任何的依赖注入,注入方式应只使用 构造函数注入 的方式,这样同时也能满足在 OOP 下的使用;
  • 组件设计时不应该通过注解进行任何的功能定义,功能定义应只通过 ConfigProvider 来定义;
  • 类的设计时应尽可能的不储存状态数据,因为这会导致这个类不能作为长生命周期的对象来提供,也无法很方便的使用依赖注入功能,这样会在一定程度下降低性能,状态数据应都通过 Hyperf\Utils\Context 协程上下文来储存;