fiberphp / container
FiberPHP framework PSR-11 dependency injection container (with singleton, contextual binding, callable injection).
dev-master
2026-08-22 08:10 UTC
Requires
- php: >=8.3
- psr/container: ^2.0
Requires (Dev)
- phpunit/phpunit: ^11.0
This package is auto-updated.
Last update: 2026-08-22 08:11:19 UTC
README
FiberPHP 框架的 PSR-11 依赖注入容器。无外部依赖(除 PSR-11 接口),支持单例绑定、上下文绑定、callable 注入、构造注入与 #[Inject] 属性注入,并内置循环依赖检测。
环境要求
- PHP >= 8.3
psr/container^2.0
安装
composer require fiberphp/container
基本用法
use FiberPHP\Container;
use Psr\Log\LoggerInterface;
// 获取全局容器单例
$container = Container::getInstance();
// 绑定接口到闭包实现
$container->bind(LoggerInterface::class, function (Container $c) {
return new FileLogger('/var/log/app.log');
});
// 单例绑定:解析一次后缓存
$container->singleton(Database::class, function (Container $c) {
return new MySQLDatabase('localhost', 'root', '');
});
// 获取已绑定实例(PSR-11 接口)
$db = $container->get(Database::class);
// 不存在时返回 null 而非抛异常(哨兵值)
$cache = $container->get('cache', Container::NULL_ON_INVALID_REFERENCE);
// has():检查是否已绑定/解析
if ($container->has(LoggerInterface::class)) {
// ...
}
// bound():与 has() 等价
$container->bound(Database::class);
// make():每次创建新实例(跳过单例缓存),可显式传参
$controller = $container->make(Controller::class, ['request' => $request]);
$fresh = $container->make(Database::class, [], true); // 强制重建
// call():调用可调用对象并自动注入方法参数
$result = $container->call(function (UserService $service) {
return $service->findAll();
});
// 也支持 [类名|实例, 方法名] 形式
$result = $container->call([$controller, 'action']);
上下文绑定
不同消费方需要同一个抽象的不同实现时使用:
use FiberPHP\Container;
$container = Container::getInstance();
// 当解析 OrderController 的依赖时,遇到 LoggerInterface 注入 FileLogger
$container->addContextual(OrderController::class, LoggerInterface::class, FileLogger::class);
// 当解析 PaymentController 的依赖时,遇到 LoggerInterface 注入 CloudLogger
$container->addContextual(PaymentController::class, LoggerInterface::class, CloudLogger::class);
// 解析时按消费方类型自动选择实现
$container->make(OrderController::class); // 内部依赖 FileLogger
$container->make(PaymentController::class); // 内部依赖 CloudLogger
属性注入
通过 #[Inject] 标注非 readonly 的实例属性,由容器在实例化后自动解析并赋值,省去构造函数样板代码。
use FiberPHP\Attribute\Inject;
use FiberPHP\Container;
class UserController
{
// 按属性类型解析
#[Inject]
private UserService $service;
// 显式指定实现类
#[Inject(UserServiceImpl::class)]
private $service2;
}
$container = Container::getInstance();
$controller = $container->make(UserController::class);
// $service 与 $service2 已自动注入
限制:
- 不可用于
readonly属性(readonly 仅能在构造期赋值),否则解析时抛ContainerException。 - 不可用于
static属性。 - 属性必须有类型声明,或在
#[Inject(ClassName::class)]中显式指定类。
异常说明
所有异常都实现 PSR-11 异常接口,便于在框架/应用层统一捕获:
FiberPHP\Exception\ClassNotFoundException:要解析的类不存在。实现Psr\Container\NotFoundExceptionInterface,对应 PSR-11get()找不到条目的场景。FiberPHP\Exception\ContainerException:其他容器错误(如循环依赖、#[Inject]误用、不可解析参数、类不可实例化)。实现Psr\Container\ContainerExceptionInterface。
License
MIT License (c) 2026 庞斌,详见 LICENSE。