如何在简单的PHP函数中使用“dependency injection”,我应该打扰吗?

我听到人们总是谈论dependency injection和它的好处,但我并不是很了解它。

我想知道如果这是“我作为参数始终传递数据库连接”的问题的解决scheme。

我尝试阅读维基百科的条目,但是这个例子是用Java编写的,所以我不太清楚它要澄清的区别。 ( http://en.wikipedia.org/wiki/Dependency_injection )。

我读了这个dependency injection在PHP文章( http://www.potstuck.com/2009/01/08/php-dependency-injection/ ),它的目标似乎是不传递依赖对象直接,而是为了封锁创build一个对象,并创build它的依赖关系。 不过我不确定如何在PHP函数中使用它。

此外,是下面的dependency injection,我应该打扰尝试在function上下文中进行dependency injection?

版本1 :(我创build的那种代码,但不喜欢,每天)

function get_data_from_database($database_connection){ $data = $database_connection->query('blah'); return $data; } 

版本2 :(不必传递数据库连接,但可能不dependency injection?)

 function get_database_connection(){ static $db_connection; if($db_connection){ return $db_connection; } else { // create db_connection ... } } function get_data_from_database(){ $conn = get_database_connection(); $data = $conn->query('blah'); return $data; } $data = get_data_from_database(); 

版本3 :(创build“对象”/数据是分开的,而数据库代码仍然是这样,所以这可能会被视为dependency injection?)

 function factory_of_data_set(){ static $db_connection; $data_set = null; $db_connection = get_database_connection(); $data_set = $db_connection->query('blah'); return $data_set; } $data = factory_of_data_set(); 

任何人都有一个良好的资源或只是洞察力,使方法和利益 – 晶莹剔透?

dependency injection是“我的构造函数中有更多参数”的一个大词汇。

这就是你在不喜欢全局variables的情况下在单纯的波形之前所做的事情:

 <?php class User { private $_db; function __construct($db) { $this->_db = $db; } } $db = new Db(); $user = new User($db); 

现在,诀窍是使用一个类来pipe理你的依赖关系,就像这样:

 class DependencyContainer { private _instances = array(); private _params = array(); public function __construct($params) { $this->_params = $params; } public function getDb() { if (empty($this->_instances['db']) || !is_a($this->_instances['db'], 'PDO') ) { $this->_instances['db'] = new PDO( $this->_params['dsn'], $this->_params['dbUser'], $this->_params['dbPwd'] ); } return $this->_instances['db']; } } class User { private $_db; public function __construct(DependencyContainer $di) { $this->_db = $di->getDb(); } } $dependencies = new DependencyContainer($someParams); $user = new User($dependencies); 

你必须认为你只是另一个阶级,更复杂。 但是,你的用户类可能需要一些东西来logging像许多其他类的消息。 只需在你的依赖容器中添加一个getMessageHandler函数,然后向你的用户类添加一些$this->_messages = $di->getMessageHandler() 。 代码的其余部分没有什么改变。

你会得到很多关于symfony的文档的信息

你的第一个例子dependency injection,你正在将数据库对象的dependency injection到函数中。

莎拉说这不是,但是,我相信她正在考虑下一级的dependency injection容器:

http://components.symfony-project.org/dependency-injection/trunk/book/02-Dependency-Injection-Containers

没有你的例子看起来像dependency injection,版本一是最接近的。 dependency injection是面向对象编程中使用的一种技术,其中对象的构造函数具有所需服务对象的参数,而这些服务对象由实例的创build者(可以是工厂,testing或dependency injection框架)。

为了避免你的“总是传递连接对象”的问题,你可能要考虑模板模式。 模板模式基本上是具有重复代码块的公共部分的抽象基类,以及允许这些重复代码块的实例之间的变化的抽象方法。 基本上是一个代码块的模板,抽象的方法是填充的空白。我个人使用模板方法模式来做我的数据库资源控制在Java中。

我已经做了很多关于这个话题(PHPdependency injection)的search,并没有find多less我喜欢的。 关于其他语言(Google Guice – http://code.google.com/p/google-guice/ ; Java Spring)的主题已经写了很多,但是我找不到很多可用的PHP。 不pipe语言如何,挑战是相似的。

你列出的三个版本是典型的方法。 版本3是最接近我看到行业走向的方向。 通过在您的课程外部创build您的依赖对象的职责,您可以自由地在testing代码中操作它们。 但是,我遇到的这种方法的问题是,您的构造函数中的长依赖对象链可能不会被接收对象使用,而是传递给次依赖对象。 它变得混乱,你失去了什么来自哪里的知识。

@Arkh和@mmmshuddup的Dependency Container示例是一个很好的开始,但是我也发现了这种方法的局限性。 我到达的最终解决scheme是一个定制的解决scheme,模仿Scala中stream行的Cake Pattern。 它允许您将单个依赖项传递给每个构造函数,并且可以让您为每个类定义依赖对象的默认构造。 这使您从长期依赖链中解脱出来,同时失去对依赖关系默认实现的控制。

我打电话给Diesel系统,我真的很高兴。 我在github上发布了任何感兴趣的代码。 你可以从我写的关于这个主题的博客中得到它,这个博客描述了基本的用法,并且对你的问题进行了更多的细节。 http://developers.blog.box.com/2012/02/15/introducting-diesel-php-dependency-injection/

dependency injection是消除2个组件之间依赖关系的思想,以便专注于为什么依赖。

假设你有一个组件A需要使用另一个组件B的服务。

如果你硬编码B中存在的B,那么当你希望A使用相同的服务,但是由另一个组件实现时,你会被卡住。

所以通常情况下,你定义了一个B和C将要实现的服务接口,并且确保当你使用A时,你用与所需接口兼容的对象来提供它。

在你的情况下,你可能会认为你的界面是一个你可以查询的服务。

你的第一个案例是更接近dependency injection的想法。