一键导入
hyperf-container
Hyperf 依赖注入容器使用指南,包括服务注册、依赖获取、自动注入等基础概念。使用当处理 Hyperf 项目中的依赖注入、Container 操作、DI 配置或服务管理时。
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
菜单
Hyperf 依赖注入容器使用指南,包括服务注册、依赖获取、自动注入等基础概念。使用当处理 Hyperf 项目中的依赖注入、Container 操作、DI 配置或服务管理时。
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
基于 SOC 职业分类
Hyperf 版本感知开发指南。当检测到项目使用 Hyperf 3.x 时,自动应用对应版本的编码规范:3.1+ 必须使用 `\Hyperf\Support\env()` 或 `use function Hyperf\Support\env` 而非全局 `env()`;3.2+ 需使用新的 Logger/Cache 配置结构。适用于代码生成、配置编写、问题诊断等所有 Hyperf 开发场景。
w7corp/easywechat 微信开发 SDK 使用指南,涵盖公众号、小程序、企业微信、微信支付等平台接口开发。包含 Hyperf 框架集成、消息处理、OAuth 授权、支付流程等。使用当开发微信相关功能、处理微信回调、实现微信登录或支付时。
| name | hyperf-container |
| description | Hyperf 依赖注入容器使用指南,包括服务注册、依赖获取、自动注入等基础概念。使用当处理 Hyperf 项目中的依赖注入、Container 操作、DI 配置或服务管理时。 |
Hyperf 基于 PSR-11 标准实现依赖注入容器,是框架的核心组件。
use Hyperf\Utils\ApplicationContext;
// 方式一:通过 ApplicationContext(推荐)
$container = ApplicationContext::getContainer();
// 方式二:在 Controller/Service 中直接注入
public function __construct(
private \Psr\Container\ContainerInterface $container
) {}
如果项目中定义了全局 di() 函数,可以简化容器访问:
检测 di() 函数是否存在:
检查项目中是否有类似以下的全局函数定义(通常在 app/Kernel/Functions.php):
use Hyperf\Context\ApplicationContext;
function di(?string $id = null)
{
$container = ApplicationContext::getContainer();
if ($id) {
return $container->get($id);
}
return $container;
}
使用方式:
// 获取容器实例
$container = di();
// 直接获取服务
$userService = di(App\Service\UserService::class);
何时建议添加 di() 函数:
ApplicationContext::getContainer()->get(...)注意: di() 是可选的便利函数,不是 Hyperf 内置功能,需手动定义。
// 直接获取实例
$userService = $container->get(App\Service\UserService::class);
// 判断服务是否存在
if ($container->has(App\Service\UserService::class)) {
$userService = $container->get(App\Service\UserService::class);
}
namespace App\Controller;
use App\Service\UserService;
use Hyperf\HttpServer\Annotation\AutoController;
#[AutoController]
class UserController
{
public function __construct(
private UserService $userService
) {}
public function index()
{
// 直接使用 $this->userService
return $this->userService->list();
}
}
优势:
Hyperf 会自动扫描 App 命名空间下的类并注册到容器,无需手动配置。
// app/Service/UserService.php
namespace App\Service;
class UserService
{
public function list(): array
{
return [];
}
}
用于第三方组件或需要自定义配置的服务:
// config/autoload/dependencies.php
return [
// 绑定接口到实现
App\Repository\UserRepositoryInterface::class => App\Repository\UserRepository::class,
// 单例模式(默认就是单例)
App\Service\CacheService::class => \Hyperf\Di\Annotation\Singleton::class,
];
对于需要手动注册的服务,应创建 Listener 监听 BootApplication 事件:
步骤 1: 创建 Listener
namespace App\Listener;
use Hyperf\Contract\ConfigInterface;
use Hyperf\Event\Annotation\Listener;
use Hyperf\Framework\Event\BootApplication;
use Psr\Container\ContainerInterface;
use Psr\EventDispatcher\ListenerProviderInterface;
#[Listener]
class ServiceRegisterListener implements ListenerProviderInterface
{
public function __construct(
private ContainerInterface $container
) {}
public function listen(): array
{
return [
BootApplication::class,
];
}
public function process(object $event): void
{
// 注册自定义服务
$this->container->set(
'custom.service',
new \App\Service\CustomService(
$this->container->get(ConfigInterface::class)
)
);
}
}
关键点:
Hyperf\Framework\Event\BootApplication 事件#[Listener] 注解让 Hyperf 自动发现process() 方法中执行服务注册逻辑当需要动态创建对象或控制实例化过程时,使用 Factory:
步骤 1: 定义接口
namespace App\Service;
interface OrderServiceInterface
{
public function create(array $data): int;
public function findById(int $id): ?array;
}
步骤 2: 实现接口
namespace App\Service;
use App\Repository\OrderRepository;
use Hyperf\DbConnection\Db;
class OrderService implements OrderServiceInterface
{
public function __construct(
private OrderRepository $orderRepository,
private int $timeout,
private Db $db
) {}
public function create(array $data): int
{
return $this->orderRepository->insert($data);
}
public function findById(int $id): ?array
{
return $this->orderRepository->find($id);
}
}
步骤 3: 创建 Factory 类
namespace App\Factory;
use App\Service\OrderService;
use App\Service\OrderServiceInterface;
use Hyperf\Contract\ConfigInterface;
use Hyperf\DbConnection\Db;
use Psr\Container\ContainerInterface;
class OrderServiceFactory
{
public function __invoke(ContainerInterface $container): OrderServiceInterface
{
// 可以在此处进行复杂的初始化逻辑
$config = $container->get(ConfigInterface::class);
$db = $container->get(Db::class);
return new OrderService(
$container->get(\App\Repository\OrderRepository::class),
$config->get('app.order_timeout', 30),
$db
);
}
}
步骤 4: 在 dependencies.php 中绑定接口到 Factory
// config/autoload/dependencies.php
return [
// 将接口绑定到 Factory,避免循环依赖
App\Service\OrderServiceInterface::class => App\Factory\OrderServiceFactory::class,
];
使用示例:
namespace App\Controller;
use App\Service\OrderServiceInterface;
use Hyperf\HttpServer\Annotation\AutoController;
#[AutoController]
class OrderController
{
public function __construct(
private OrderServiceInterface $orderService
) {}
public function create()
{
$id = $this->orderService->create(['product_id' => 1]);
return ['id' => $id];
}
}
适用场景:
关键注意:
| 方式 | 适用场景 | 示例 |
|---|---|---|
| 构造函数注入 | 大部分场景(推荐) | __construct(private UserService $service) |
| Factory 工厂 | 复杂初始化、动态创建 | 创建 Factory 类并在 dependencies.php 绑定 |
| Listener 注册 | 应用启动时注册服务 | 监听 BootApplication 事件 |
| 方法注入 | 中间件、事件监听器 | public function handle(Context $ctx, Closure $next) |
| 属性注入 | 不推荐,仅用于特殊情况 | 使用 @Inject 注解 |
| 容器获取 | 无法使用注入的场景 | $container->get(Service::class) |
namespace App\Service;
use App\Repository\UserRepository;
class UserService
{
public function __construct(
private UserRepository $userRepository
) {}
public function findById(int $id): ?array
{
return $this->userRepository->find($id);
}
}
namespace App\Service;
use App\Repository\UserRepository;
use App\Repository\OrderRepository;
use Hyperf\DbConnection\Db;
class OrderService
{
public function __construct(
private UserRepository $userRepository,
private OrderRepository $orderRepository,
private Db $db
) {}
}
当 A 依赖 B,B 又依赖 A 时:
// 方案一:使用容器延迟获取
class ServiceA
{
private ?ServiceB $serviceB = null;
public function __construct(
private \Psr\Container\ContainerInterface $container
) {}
private function getServiceB(): ServiceB
{
if (!$this->serviceB) {
$this->serviceB = $this->container->get(ServiceB::class);
}
return $this->serviceB;
}
}
// 方案二:重构代码,提取共同依赖到第三个服务
// 在任意可注入的地方
public function debug(\Psr\Container\ContainerInterface $container)
{
// 检查服务是否注册
var_dump($container->has(UserService::class));
// 获取服务定义(需要安装 hyperf/di 调试工具)
}