PHP中的依赖注入:初学者简易指南

面向初学者的在线Python训练器

轻松学习Python,无需理论负担。在浏览器中直接解决带自动检查的实践任务,无需安装任何东西。

开始课程

PHP中的依赖注入:面向初学者



想象一下你在组装一台电脑。你不会把处理器永久焊在主板上——而是将其插入一个专用插槽,以便在需要时更换为更强大的型号。PHP中的依赖注入(DI)遵循同样的原则:不在类内部创建依赖,而是从外部“注入”它们。



在本文中,我们将探讨什么是依赖注入、为什么需要它,以及如何在PHP中应用它。你将了解如何使代码更灵活、更易于测试和维护。



用简单的话说什么是依赖注入



依赖注入是一种设计模式,对象从外部获取其依赖(其他对象、服务),而不是自己创建它们。与其在类内部写new Database(),不如通过构造函数或setter方法传入一个现成的数据库对象。



让我们看看DI解决的问题。考虑一个直接创建数据库连接的UserService类:



<?phpclass UserService {    private $db;        public function __construct() {        // 与具体实现紧密耦合        $this->db = new MySQLConnection('localhost', 'user', 'pass');    }        public function getUser($id) {        return $this->db->query("SELECT * FROM users WHERE id = $id");    }}?>


这种方法的缺点显而易见:



  • 紧耦合——UserService类与MySQLConnection绑定。要切换到PostgreSQL,必须修改类的代码。
  • 测试困难——在单元测试中无法将数据库替换为mock对象。
  • 违反单一职责原则——类不仅处理用户相关操作,还负责创建数据库连接。


现在用依赖注入重写这个类:



<?phpinterface DatabaseInterface {    public function query($sql);}

class MySQLConnection implements DatabaseInterface { public function query($sql) { // MySQL的实现 }}

class PostgreSQLConnection implements DatabaseInterface { public function query($sql) { // PostgreSQL的实现 }}

class UserService { private $db; // 通过构造函数注入依赖 public function __construct(DatabaseInterface $db) { $this->db = $db; } public function getUser($id) { return $this->db->query("SELECT * FROM users WHERE id = $id"); }}

// 使用$db = new MySQLConnection('localhost', 'user', 'pass');$userService = new UserService($db);?>


现在UserService不知道它具体使用哪个数据库。它只使用DatabaseInterface接口。这就是依赖注入的本质。



三种主要的依赖注入类型



在PHP中,有三种主要的依赖注入方式。我们来逐一了解。



1. 构造函数注入



这是最常见且推荐的方式。依赖通过构造函数参数传递,并保存在类的私有属性中。



<?phpclass Logger {    private $writer;        public function __construct(LogWriterInterface $writer) {        $this->writer = $writer;    }        public function log($message) {        $this->writer->write($message);    }}?>


优点:依赖关系清晰可见,对象始终处于有效状态(所有依赖都是必需的)。



缺点:如果

博客

书籍推荐