代码之家  ›  专栏  ›  技术社区  ›  Kzqai JW.

我如何在简单的PHP函数中使用“依赖项注入”,我该怎么做呢?

  •  67
  • Kzqai JW.  · 技术社区  · 14 年前

    我经常听到人们谈论依赖注入和它的好处,但我并不真正理解。

    我想知道这是否是解决“我一直将数据库连接作为参数传递”问题的解决方案。

    我试着阅读维基百科的条目,但是这个例子是用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;
    }
    

    版本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();
    

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

    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();
    

    有没有人有一个很好的资源或洞察力,使方法和效益——清晰明了?

    5 回复  |  直到 10 年前
        1
  •  75
  •   Arkh    10 年前

    依赖注入是“我的构造函数中有更多的参数”的一个大字。

    当你不喜欢环球赛的时候,这就是你在单打浪潮之前所做的:

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

    现在,技巧是使用一个类来管理依赖项,类似于:

    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);
    

    你必须认为你只是另一个类,更复杂。但是,您的用户类可能需要一些东西来记录消息,就像许多其他类一样。只需将getmessagehandler函数添加到依赖容器,以及 $this->_messages = $di->getMessageHandler() 到您的用户类。其余代码中没有可更改的内容。

    你会得到很多信息的 symfony's doc

        2
  •  13
  •   jmoz    14 年前

    你的第一个例子 依赖注入,您正在将对数据库对象的依赖注入函数中。

    莎拉说这不是,但在我看来,我相信她正在考虑下一个层次的依赖注入容器:

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

        3
  •  7
  •   Sarah Happy    14 年前

    您的示例中没有一个看起来像依赖注入,但是版本1是最接近的。依赖注入是面向对象编程中使用的一种技术,其中对象的构造函数具有它所需的服务对象的参数,这些服务对象由实例的创建者传入(可以是工厂、测试或依赖注入框架)。

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

        4
  •  2
  •   Ben    12 年前

    我自己对这个主题做了很多搜索(PHP依赖项注入),但没有找到我喜欢的内容。关于其他语言(google guice)的主题已经写了很多文章- http://code.google.com/p/google-guice/ JavaSpring),但我找不到很多可用的PHP。然而,不管语言如何,挑战是相似的。

    您在问题中列出的三个版本是典型的方法。版本3最接近我所看到的行业发展方向。通过将创建依赖对象的责任转移到类之外,您可以随意地在测试代码中操纵它们。但是,我在这种方法中遇到的问题是,在构造函数中,依赖对象的长链最终可能甚至不能被接收对象使用,而是传递给次要的依赖对象。它变得杂乱无章,你就会失去从哪里来的知识。

    @arkh和@mmmshuddup的依赖容器示例是一个很好的开始,但是我也发现了这种方法的局限性。我到达的最后一个解决方案是一个定制的解决方案,在某种程度上模仿了scala中流行的蛋糕模式。它允许您将单个依赖项传递给每个构造函数,并允许您定义依赖对象的默认构造。 类。这将使您从长的依赖链中解放出来,并失去对依赖项的默认实现的控制。

    我给系统打电话叫柴油机,我对它很满意。我在Github上为感兴趣的人发布了代码。你可以从我写的关于这个主题的博客中找到它,它描述了基本用法,并对你的问题进行了更详细的讨论。 http://developers.blog.box.com/2012/02/15/introducting-diesel-php-dependency-injection/

        5
  •  2
  •   Jerome WAGNER    12 年前

    依赖注入是一种消除两个组件之间的依赖关系的思想,目的是关注它们依赖的原因。

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

    如果您在A中硬编码B的存在,那么当您希望A使用SAMES服务,但由另一个组件实现时,您将陷入困境。

    因此,通常情况下,您定义一个B和C将实现的服务接口,并确保在使用A时,向它提供与所需接口兼容的对象。

    在您的案例中,您可能会认为您的接口是一个可以进行查询的服务。

    您的第一个案例更接近依赖注入的概念。