【问题标题】:Dependency Injection simple implementation依赖注入简单实现
【发布时间】:2011-01-03 02:09:50
【问题描述】:

在阅读this 问题后,我想知道是否有人可以帮助我了解如何使用这些 PHP 类正确实现依赖注入:

class DBClass
{
    private $mMysqli;
    function  __construct(mysqli $database)
    {
        $this->mMysqli=$database;
    }
    function __destruct()
    {
        $this->mMysqli->close();
    }

    public function listUsers()
    {
        $query='SELECT * FROM Utente;';
        $resultset=$this->mMysqli->query($query);
        while($row = $resultset->fetch_array(MYSQLI_ASSOC)) {
            echo $row['username'];
            echo $row['pwd'];
            echo "<br />\n";
        }

    }

    public function runQuery($query)
    {
        return $resultset=$this->mMysqli->query($query);
    }

    public function getConnection()
    {
        return $this->mMysqli;
    }
}

会话类:

class Session
{
    private $_session;
    public $maxTime;
    private $database;

    public function __construct(DBClass $database)
    {
        $this->database=$database;
        $this->maxTime['access'] = time();
        $this->maxTime['gc'] = get_cfg_var('session.gc_maxlifetime');
        session_set_save_handler(array($this,'_open'),
                array($this,'_close'),
                array($this,'_read'),
                array($this,'_write'),
                array($this,'_destroy'),
                array($this,'_clean')
                );
        register_shutdown_function('session_write_close');
        session_start();
        ...
     }
}   

用户类(有关当前登录用户的详细信息):

class User
{
    private $username;
    private $role;
    private $session;

    function __construct($session)
    {
        $this->session=$session;
        ...
    }
}

对外:

$connection=new mysqli(DB_HOST, DB_USER, DB_PASSWORD, DB_DATABASE);
$database=new DBClass($connection);
$session=new Session($database);
$user=new User($session);

这是正确的方法吗?

【问题讨论】:

    标签: php oop design-patterns


    【解决方案1】:

    是的。您现在通过提供更少耦合的构造函数注入依赖项。您现在可以更轻松地换出这些依赖项,例如进行单元测试时,您可以将它们替换为 Mocks。

    尽管使用具体的 DBClass 作为 TypeHint 而不是 interface,但仍然有一些耦合。因此,当您想使用不同的 DBClass 时,必须将其命名为 DBClass。您可以通过coding against an interface 实现更松散的耦合,而具体类必须实现。

    要仅创建类的单个实例(如 cmets 中所要求的),您可以使用 Singleton(如 Kevin Peno 建议的那样)或 Factory 来创建并跟踪实例是否已创建。或者使用 DI 服务容器,它类似于工厂,但不是一回事。它为您创建和管理对象。

    Symfony Components library has a Dependency Injection Container 具有出色的文档和关于如何使用服务容器进一步增强 DI 的主题介绍。容器也可以用来限制实例。看看吧。

    【讨论】:

    • 感谢您的回答,但是如何使用 DI 仅实例化一个对象的一个​​实例,例如数据库连接?
    • 我已经更新了答案。看看它,请帮自己一个忙,看看 Symfony 中的服务容器。真的很强大。
    • 谢谢,我一定会去看看的!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-14
    相关资源
    最近更新 更多