php实现di
PHP 实现依赖注入(DI)的方法
依赖注入(Dependency Injection,DI)是一种设计模式,用于解耦代码并提高可测试性。以下是几种在 PHP 中实现 DI 的方式:
手动依赖注入
通过构造函数或方法参数显式传递依赖对象。这种方式简单直接,适合小型项目。
class Database {
public function query($sql) {
// 执行数据库查询
}
}
class UserService {
private $db;
public function __construct(Database $db) {
$this->db = $db;
}
public function getUsers() {
return $this->db->query('SELECT * FROM users');
}
}
// 使用
$db = new Database();
$userService = new UserService($db);
使用容器实现 DI
依赖注入容器(DIC)可以自动管理依赖关系。以下是简单容器的实现示例:

class Container {
private $instances = [];
public function set($name, callable $resolver) {
$this->instances[$name] = $resolver;
}
public function get($name) {
if (isset($this->instances[$name])) {
return $this->instances[$name]();
}
throw new Exception("未找到依赖: {$name}");
}
}
// 配置容器
$container = new Container();
$container->set('db', function() {
return new Database();
});
$container->set('userService', function() use ($container) {
return new UserService($container->get('db'));
});
// 使用
$userService = $container->get('userService');
使用第三方库
许多 PHP 框架和库提供了成熟的 DI 容器实现:
-
PHP-DI:功能丰富的依赖注入容器

use DI\ContainerBuilder; $builder = new ContainerBuilder(); $builder->addDefinitions([ 'db' => function() { return new Database(); }, 'userService' => \DI\create(UserService::class) ->constructor(\DI\get('db')) ]); $container = $builder->build(); $userService = $container->get('userService'); -
Laravel 服务容器:Laravel 框架内置的 DI 容器
app()->bind('db', function() { return new Database(); }); app()->bind('userService', function($app) { return new UserService($app->make('db')); }); $userService = app()->make('userService');
自动装配(Autowiring)
现代 DI 容器通常支持自动解析依赖关系:
// PHP-DI 示例
$builder = new ContainerBuilder();
$builder->useAutowiring(true);
$container = $builder->build();
// 自动解析 UserService 的依赖
$userService = $container->get(UserService::class);
接口绑定
将接口绑定到具体实现,提高灵活性:
interface DatabaseInterface {
public function query($sql);
}
class MySQLDatabase implements DatabaseInterface {
public function query($sql) {
// MySQL 实现
}
}
// 容器配置
$container->set(DatabaseInterface::class, function() {
return new MySQLDatabase();
});
// 使用接口类型提示
class UserService {
public function __construct(DatabaseInterface $db) {
// ...
}
}
最佳实践
- 优先使用构造函数注入,保持依赖关系明确
- 对于复杂项目,考虑使用成熟的 DI 容器库
- 结合接口编程,提高代码的可替换性和可测试性
- 避免服务定位器模式(Service Locator),它实际上是反模式
通过合理使用依赖注入,可以显著提高代码的可维护性和可测试性,特别是在大型应用程序中。






