woocommerce/.ai/skills/woocommerce-backend-dev/zh-cn/dependency-injection.md
2026-04-15 10:18:01 +08:00

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 ); // 工厂方法
```
## 为什么使用依赖注入?
- 易于在测试中进行模拟
- 无需更改代码即可交换依赖项
- 签名中明确的依赖关系