102 lines
No EOL
2.8 KiB
Markdown
102 lines
No EOL
2.8 KiB
Markdown
# 依赖注入
|
|
|
|
## 目录
|
|
|
|
- [`src/` 类的标准 DI 样板](#standard-di-pattern-for-src-classes)
|
|
- [初始化设置钩子的类](#initializing-classes-that-set-up-hooks)
|
|
- [使用容器获取实例](#using-the-container-to-get-instances)
|
|
- [为什么使用依赖注入?](#why-use-dependency-injection)
|
|
|
|
## `src/` 类的标准 DI 样板
|
|
|
|
依赖项通过带有 `@internal` 注解的 `final` `init` 方法注入(前后留空行)。
|
|
|
|
**示例:**
|
|
|
|
```php
|
|
namespace Automattic\WooCommerce\Internal\Admin;
|
|
|
|
use Automattic\WooCommerce\Internal\Logging\Logger;
|
|
use Automattic\WooCommerce\Internal\DataStore\OrderDataStore;
|
|
|
|
class OrderProcessor {
|
|
private Logger $logger;
|
|
private OrderDataStore $data_store;
|
|
|
|
/**
|
|
* 使用依赖项初始化订单处理器。
|
|
*
|
|
* @internal
|
|
*
|
|
* @param Logger $logger 日志记录器实例。
|
|
* @param OrderDataStore $data_store 订单数据存储。
|
|
*/
|
|
final public function init( Logger $logger, OrderDataStore $data_store ) {
|
|
$this->logger = $logger;
|
|
$this->data_store = $data_store;
|
|
}
|
|
|
|
public function process( int $order_id ) {
|
|
$this->logger->log( "Processing order {$order_id}" );
|
|
// ...
|
|
}
|
|
}
|
|
```
|
|
|
|
## 初始化设置钩子的类
|
|
|
|
在 `includes/class-woocommerce.php` 的 `init_hooks()` 中添加:
|
|
|
|
- 使用 `$container->get( ClassName::class );`
|
|
- 添加到“这些类在实例化时设置钩子”部分的末尾
|
|
|
|
**`includes/class-woocommerce.php` 中的示例:**
|
|
|
|
```php
|
|
private function init_hooks() {
|
|
// ... 现有代码 ...
|
|
|
|
// 这些类在实例化时设置钩子
|
|
$container->get( SomeExistingClass::class );
|
|
$container->get( AnotherExistingClass::class );
|
|
$container->get( YourNewClass::class ); // 在此处添加你的新类
|
|
}
|
|
```
|
|
|
|
## 使用容器获取实例
|
|
|
|
当需要在代码的其他地方从容器获取类的实例时:
|
|
|
|
```php
|
|
use Automattic\WooCommerce\Internal\Utils\DataParser;
|
|
|
|
// 从容器获取实例
|
|
$parser = wc_get_container()->get( DataParser::class );
|
|
```
|
|
|
|
### 单例行为
|
|
|
|
**重要:** 容器总是检索给定类的相同实例(单例模式)。
|
|
|
|
当需要不同的实例时(且仅在此情况下),使用 `new` 或该类的适当工厂方法(如果可用)。
|
|
|
|
**示例:**
|
|
|
|
```php
|
|
// 每次都是相同的实例 - 使用容器
|
|
$logger = wc_get_container()->get( Logger::class );
|
|
$same_logger = wc_get_container()->get( Logger::class ); // 与上面相同的实例
|
|
|
|
// 需要不同的实例 - 使用 new 或工厂
|
|
$order1 = new WC_Order( 123 );
|
|
$order2 = new WC_Order( 456 ); // 不同的实例
|
|
|
|
// 使用可用的工厂方法
|
|
$product = wc_get_product( 789 ); // 工厂方法
|
|
```
|
|
|
|
## 为什么使用依赖注入?
|
|
|
|
- 易于在测试中进行模拟
|
|
- 无需更改代码即可交换依赖项
|
|
- 签名中明确的依赖关系 |