php 实现 ioc
PHP 实现 IOC(控制反转)容器
控制反转(IoC)是一种设计模式,用于解耦依赖关系。在 PHP 中,可以通过依赖注入(DI)手动实现,或使用容器自动管理依赖。
手动依赖注入实现
通过构造函数或方法参数显式传递依赖对象,实现解耦。
class Database {
public function query($sql) {
// 数据库查询逻辑
}
}
class UserRepository {
private $db;
public function __construct(Database $db) {
$this->db = $db;
}
public function getUsers() {
return $this->db->query('SELECT * FROM users');
}
}
// 使用
$db = new Database();
$userRepo = new UserRepository($db);
简单 IOC 容器实现
创建一个容器类,用于注册和解析依赖关系。
class Container {
protected $bindings = [];
public function bind($abstract, $concrete) {
$this->bindings[$abstract] = $concrete;
}
public function make($abstract) {
if (isset($this->bindings[$abstract])) {
$concrete = $this->bindings[$abstract];
if (is_callable($concrete)) {
return $concrete($this);
}
return new $concrete();
}
throw new Exception("No binding found for {$abstract}");
}
}
// 使用示例
$container = new Container();
$container->bind('Database', function() {
return new Database();
});
$container->bind('UserRepository', function($container) {
return new UserRepository($container->make('Database'));
});
$userRepo = $container->make('UserRepository');
自动依赖解析
通过反射自动解析类的依赖关系,无需手动绑定。
class Container {
public function make($className) {
$reflector = new ReflectionClass($className);
if (!$reflector->isInstantiable()) {
throw new Exception("Class {$className} is not instantiable");
}
$constructor = $reflector->getConstructor();
if (is_null($constructor)) {
return new $className();
}
$parameters = $constructor->getParameters();
$dependencies = [];
foreach ($parameters as $parameter) {
$dependency = $parameter->getClass();
if (is_null($dependency)) {
if ($parameter->isDefaultValueAvailable()) {
$dependencies[] = $parameter->getDefaultValue();
} else {
throw new Exception("Cannot resolve class dependency {$parameter->name}");
}
} else {
$dependencies[] = $this->make($dependency->name);
}
}
return $reflector->newInstanceArgs($dependencies);
}
}
// 使用
$container = new Container();
$userRepo = $container->make('UserRepository');
使用现有 IOC 容器库
PHP 生态系统中有多个成熟的 IOC 容器实现:
-
PHP-DI: 功能丰富的依赖注入容器
use DI\ContainerBuilder; $builder = new ContainerBuilder(); $builder->addDefinitions([ 'Database' => function() { return new Database(); } ]); $container = $builder->build(); -
Laravel 容器: Laravel 框架的 IOC 容器也可独立使用
$container = new Illuminate\Container\Container(); $container->bind('Database', function() { return new Database(); });
最佳实践建议
- 优先考虑使用构造函数注入,它使依赖关系更明确
- 对于简单项目,手动依赖注入可能足够
- 复杂项目建议使用成熟的容器库如 PHP-DI
- 避免服务定位器模式(直接从容器的全局实例获取依赖),这会使代码更难测试
通过以上方法可以在 PHP 项目中实现控制反转,提高代码的可测试性和可维护性。







