fiberphp/container

FiberPHP framework PSR-11 dependency injection container (with singleton, contextual binding, callable injection).

Maintainers

Package info

gitee.com/FiberPHP/container.git

Issues

pkg:composer/fiberphp/container

Transparency log

Statistics

Installs: 12

Dependents: 1

Suggesters: 0

dev-master 2026-08-22 08:10 UTC

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-11 get() 找不到条目的场景。
  • FiberPHP\Exception\ContainerException:其他容器错误(如循环依赖、#[Inject] 误用、不可解析参数、类不可实例化)。实现 Psr\Container\ContainerExceptionInterface

License

MIT License (c) 2026 庞斌,详见 LICENSE