这是一个简单高效的 PHP 依赖注入包,它使用了 PHP 的最新特性:注解。通过注解,我们可以将一个类标记为单例。
PHP 版本
最低支持的 PHP 版本:8.0
介绍
- 无依赖
- 支持单例模式
- 支持类别名
- 支持类映射
- 反射对象缓存消除了重复创建相同类反射的需求,并提高了性能
- 循环依赖检测,能够检测循环依赖问题(包括直接和间接循环依赖)
安装
composer require yolo-fx/di
使用方法
- 创建类的实例。
你可以使用 Yolo\Di\DI::use()
来创建类的实例,例如:
Yolo\Di\DI::use(User::class)
- 单例
你可以使用 Yolo\Di\Annotations\Singleton
注解来将一个类标记为单例。
- 初始化器
你可以使用 Yolo\Di\Annotations\Initializer
注解来将一个方法标记为初始化器。
- 使用类映射
当你的构造函数参数是一个接口类型时,这会非常有用。例如:
class TestRunner
{
/**
* @param LoggerInterface $logger It will be replaced by ConsoleLogger
*/
public function __construct(private LoggerInterface $logger)
{
}
public function sayHello(): void
{
$this->logger->log("Hello World");
}
}
你可以使用 Yolo\Di\DI::bind()
来设置类映射。
DI::bind(LoggerInterface::class, ConsoleLogger::class);
这样 LoggerInterface::class
将被 ConsoleLogger::class
替换。
现在,你可以使用 Yolo\Di\DI::use()
来创建类的实例。
$runner = DI::use(TestRunner::class);
$runner->sayHello();
- 使用类别名
DI::alias(TestRunner::class, 'runner');
$runner = DI::use('runner');
$runner->sayHello();
示例
- 创建一个类: UserTest.php
<?php
namespace DI\Tests;
use Yolo\Di\Annotations\Initializer;
class UserTest
{
public function __construct(private AnimalTest $animal)
{
echo "you can see me twice." . PHP_EOL;
}
#[Initializer]
public function init()
{
echo "User.init" . PHP_EOL;
}
/**
* Say hello
* @return void
*/
public function sayHello()
{
echo "Hello, I am a user." . PHP_EOL;
$this->animal->sayHello();
}
}
- 创建另一个类: AnimalTest.php
<?php
namespace DI\Tests;
use Yolo\Di\Annotations\Singleton;
#[Singleton]
class AnimalTest
{
public function __construct()
{
echo 'you can only see me once' . PHP_EOL;
}
public function sayHello()
{
echo 'Hello, I am an animal.' . PHP_EOL;
}
}
- 使用 DI 创建实例
<?php
use Yolo\Di\DI;
require_once __DIR__ . '/../vendor/autoload.php';
require_once __DIR__ . '/LoggerInterface.php';
require_once __DIR__ . '/ConsoleLogger.php';
require_once __DIR__ . '/FileLogger.php';
class TestRunner
{
public function __construct(private LoggerInterface $logger)
{
}
public function sayHello(): void
{
$this->logger->log("Hello World");
}
}
$start = microtime(true);
DI::bind(LoggerInterface::class, ConsoleLogger::class);
// Use DI::alias to create an alias for a class
DI::alias(TestRunner::class, 'runner');
// And then use the alias to create an instance of TestRunner
$runner = DI::use('runner');
$runner->sayHello();
// Also, you can use the class name to create an instance of TestRunner
$runner = DI::use(TestRunner::class);
$runner->sayHello();
$end = microtime(true);
echo 'Spent ' . round(($end - $start) * 6, 3) . 'ms' . PHP_EOL;
echo 'Memory usage: ' . round(memory_get_usage() / 1024, 3) . 'kb' . PHP_EOL;
注意事项
- 不要有循环依赖,包括直接和间接的循环依赖,比如 A 依赖于 B 而 B 又依赖于 A。
近期评论