Merge pull request #280 from zhamao-robot/add-container-docs

添加依赖注入组件文档
This commit is contained in:
sunxyw 2023-02-07 18:57:07 +08:00 committed by GitHub
commit 6df1f9a70a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 197 additions and 2 deletions

1
.gitignore vendored
View File

@ -51,6 +51,7 @@ cghooks.lock
/node_modules/
/docs/.vuepress/dist/
package-lock.json
pnpm-lock.yaml
### PHPUnit ###

View File

@ -104,6 +104,16 @@ module.exports = {
'store/cache',
'store/redis',
]
},
{
title: '依赖注入组件',
collapsable: true,
sidebarDepth: 2,
children: [
'container/dependency-injection',
'container/configuration',
'container/dependencies',
],
}
],
'/advanced/': [

View File

@ -0,0 +1,41 @@
# 容器配置
我们在 `config/container.php` 中提供了详细的容器配置说明。
以下内容未必准确,请以 `config/container.php` 为准。
```php
/*
* 这里是容器的配置文件,你可以在这里配置容器的绑定和其他一些参数。
* 选用的容器是 PHP-DI你可以在这里查看文档https://php-di.org/doc/
* 我们建议你在使用容器前先阅读以下章节:
* - 基本使用方式https://php-di.org/doc/container.html
* - 注册绑定方式https://php-di.org/doc/php-definitions.html#definition-types
* - 最佳使用实践https://php-di.org/doc/best-practices.html
* 同时,你也可以选择查阅我们(炸毛框架)的相关文档,其会包含一些简单的使用方法和示例。
* 关于框架在不同事件(或周期中)默认注册的绑定,请参阅我们的文档,或直接查看 {@see \ZM\Container\ContainerRegistrant}
*/
return [
// 这里定义的是全局容器的绑定,不建议在此处直接调用框架、应用内部的类或方法,因为这些类可能还没有被加载或初始化
// 你可以使用匿名函数来延迟加载
'definitions' => [
'worker_id' => fn () => ProcessManager::getProcessId(),
Driver::class => fn () => Framework::getInstance()->getDriver(),
LoggerInterface::class => fn () => logger(),
EnvironmentInterface::class => Environment::class,
],
// 容器的缓存配置,默认情况下,只有在生产环境下才会启用缓存
// 启用缓存后可以减少重复反射的开销,在首次解析后直接从缓存中读取
// 此功能要求 APCu 扩展,如果你没有安装,将会输出警告并禁用缓存
// 请在更新容器配置后手动执行 `apcu_clear_cache()` 来清除缓存
// 详细介绍请参阅https://php-di.org/doc/performances.html#caching
'cache' => [
// 是否启用缓存,支持 bool、callable
'enable' => fn () => ZMConfig::getInstance()->getEnvironment() === 'production',
'namespace' => 'zm',
],
];
```
对于大部分使用者,你只需要在 `definitions` 中添加你需要的绑定即可。

View File

@ -0,0 +1,57 @@
# 内置依赖项
在不同的事件(或周期中),可用的依赖项可能会有所不同。例如,当你在一个命令方法中可以使用 `BotContext` 依赖,但在一个路由方法中却不能使用。
你也可以选择直接查看 `src/ZM/Container/ContainerRegistrant.php` 文件,大部分依赖都在该处定义。
GitHub 链接https://github.com/zhamao-robot/zhamao-framework/blob/main/src/ZM/Container/ContainerRegistrant.php
本页面列出在不同事件中可用的依赖项。
## 全局依赖
在任何事件(或任何支持依赖注入的地方)中,你都可以使用以下依赖项:
- `Psr\Log\LoggerInterface`:日志记录器
- `Psr\Container\ContainerInterface`:容器
- `DI\Container`:容器,区别在于可以使用 `set` 方法来动态设置依赖项,与 `container` 函数返回的实例相同
- `ZM\Config\ZMConfig`:配置,与 `config` 函数返回的实例相同
- ...
## OneBot 事件
在 OneBot 事件(`@BotEvent`)中,你可以使用以下依赖项:
- `OneBot\V12\Object\OneBotEvent`:当前事件的实例
- `ZM\Context\BotContext`:当前事件的上下文,部分事件可能不可用(要求传入的事件存在 `platform` 字段)
## OneBot 动作响应
在 OneBot 动作响应(`@BotActionResponse`)中,你可以使用以下依赖项:
- `OneBot\V12\Object\ActionResponse`:当前动作响应的实例
## HTTP 请求事件(路由事件)
在 HTTP 请求事件(`@Route`)中,你可以使用以下依赖项:
- `OneBot\Driver\Event\Http\HttpRequestEvent`:当前事件的实例
- `Psr\Http\Message\ServerRequestInterface`:当前请求的实例
## WebSocket 连接事件
在 WebSocket 连接事件(`@BindEvent(WebSocketOpenEvent::class)`)中,你可以使用以下依赖项:
- `OneBot\Driver\Event\WebSocket\WebSocketOpenEvent`:当前事件的实例
## WebSocket 消息事件
在 WebSocket 消息事件(`@BindEvent(WebSocketMessageEvent::class)`)中,你可以使用以下依赖项:
- `OneBot\Driver\Event\WebSocket\WebSocketMessageEvent`:当前事件的实例
- `Choir\WebSocket\FrameInterface`:当前消息(帧)的实例
## WebSocket 关闭事件
在 WebSocket 关闭事件(`@BindEvent(WebSocketCloseEvent::class)`)中,你可以使用以下依赖项:
- `OneBot\Driver\Event\WebSocket\WebSocketCloseEvent`:当前事件的实例

View File

@ -0,0 +1,86 @@
# 依赖注入
依赖注入这个名词并没有你想象的那么复杂,实际上它就是把一个类的依赖通过构造函数或者 setter
方法注入到类中。这样做的好处是,你可以在不修改类的情况下,通过修改容器定义来改变依赖的值。
下方是一个简单的例子,它展示了如何使用依赖注入来获取框架提供的依赖:
```php
<?php
use ZM\Context\BotContext;
class SampleModule
{
#[BotCommand('hello', 'hello')]
public function sayHello(BotContext $context): void
{
$context->reply($event->getMessage());
}
}
```
在上面的例子中,`BotContext` 类是一个依赖,它通过依赖注入注入到 `sayHello` 方法中。
另一方面,你也可以利用依赖注入来注入你自己的依赖:
```php
<?php
use MyApp\UserRepositoryInterface;
class SampleModule
{
public function __construct(UserRepositoryInterface $userRepository)
{
$this->userRepository = $userRepository;
}
}
```
在上面的例子中,`UserRepositoryInterface` 是一个接口,它的实现类是通过构造函数注入到 `SampleModule` 类中的。
`UserRepositoryInterface`
定义了从数据库中获取用户信息的方法。对于调用者来说,它并不关心具体的实现类是什么,只需要知道它实现了 `UserRepositoryInterface`
接口即可。
因此,我们可以轻易地切换 `UserRepositoryInterface` 的实现类,而不需要修改 `SampleModule`
类。此外,当需要为该类编写测试时,我们也可以很轻松地模拟或是创建一个伪实现来操作。
## 零配置依赖注入
如果一个类没有依赖项或只依赖于已经在容器中定义的类,那么你可以不用做任何配置就可以使用依赖注入解析它。
例如:
```php
<?php
class TestService
{
public function __construct()
{
// ...
}
}
```
在上面的例子中,`TestService` 类没有依赖项,因此你可以直接使用依赖注入来解析它:
```php
<?php
use TestService;
class SampleModule
{
public function __construct(TestService $testService)
{
$this->testService = $testService;
}
}
```
## 何时使用依赖注入
我们尽力在框架的大部分地方都支持使用依赖注入,例如命令、路由、中间件等。你可以在这些地方使用依赖注入来获取依赖。

View File

@ -1,7 +1,7 @@
{
"dependencies": {
"vuepress-theme-antdocs": "^1.4.5",
"vuepress": "^1.9.7"
"vuepress": "^1.9.8",
"vuepress-theme-antdocs": "^1.4.6"
},
"scripts": {
"docs:dev": "vuepress dev docs",