如何在简单的PHP函数中使用"依赖注入",我应该打扰吗?

Kzq*_*qai 67 php dependency-injection parameter-passing

我听到人们一直在谈论依赖注入和它的好处,但我真的不明白它.

我想知道它是否是"我一直将数据库连接作为参数传递"问题的解决方案.

我试过阅读维基百科上的条目,但这个例子是用Java编写的,所以我不能完全理解它试图弄清楚它的区别.(http://en.wikipedia.org/wiki/Dependency_injection).

我读了这篇依赖注入的php文章(http://www.potstuck.com/2009/01/08/php-dependency-injection/),似乎目标是不将依赖项传递给对象直接,但封锁对象的创建以及它的依赖关系的创建.不过,我不知道如何在使用php函数上下文中应用它.

另外,是以下的依赖注入,我是否应该尝试在功能上下文中进行依赖注入?

版本1 :(我创建的代码类型,但每天都不喜欢)

function get_data_from_database($database_connection){
    $data = $database_connection->query('blah');
    return $data;
}
Run Code Online (Sandbox Code Playgroud)

版本2 :(不必传递数据库连接,但可能不是依赖注入?)

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();
Run Code Online (Sandbox Code Playgroud)

版本3 :("对象"/数据的创建是独立的,数据库代码仍然是,所以这可能算作依赖注入?)

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();
Run Code Online (Sandbox Code Playgroud)

任何人都有良好的资源或只是洞察力,使方法和利益 - 水晶 - 清楚?

Ark*_*rkh 75

依赖注入是"我的构造函数中有更多参数"的一个重要词.

当你不喜欢全局变量时,你就是在糟糕的Singleton波之前所做的事情:

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

$db   = new Db();
$user = new User($db);
Run Code Online (Sandbox Code Playgroud)

现在,诀窍是使用单个类来管理您的依赖项,类似于:

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);
Run Code Online (Sandbox Code Playgroud)

你必须认为你只是另一个阶级而且更复杂.但是,您的用户类可能需要一些东西来记录许多其他类的消息.只需将getMessageHandler函数添加到依赖项容器中,将一些函数添加$this->_messages = $di->getMessageHandler()到您的用户类中.其余代码无需更改.

你会在symfony的doc上获得很多信息

  • 感谢您提供易于理解的快速启动PDO示例,并将其与您对实际问题的答案捆绑在一起:) (2认同)
  • 作为第一个看到它的人,我感到很疯狂,但这是第一个字(很好的回答),而不是正确的词? (2认同)
  • 这是反模式的完美例子.你实际上并没有做依赖注入,你只是传递容器.这实际上*隐藏了类的依赖关系,这与依赖注入点完全相反. (2认同)

jmo*_*moz 13

您的第一个示例是IS依赖注入,您将数据库对象的依赖注入到函数中.

Sarah已经说过这不是,但就是这样,我相信她正在考虑下一级别的依赖注入容器:

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


Sar*_*ppy 7

您的示例都不像依赖注入,第一版是最接近的.依赖注入是一种用于面向对象编程的技术,其中对象的构造函数具有所需服务对象的参数,并且这些服务对象由实例的创建者传入(可以是工厂,测试或依赖注入框架).

要绕过"始终传递连接对象"问题,您可能需要考虑模板模式.模板模式基本上是具有重复代码块的公共部分的抽象基类,以及允许这些重复代码块的实例之间的变化的抽象方法.基本上,base是一个代码块的模板,抽象方法是要填充的空白.我个人使用模板方法模式在Java中进行数据库资源控制.