dongyuqi3808 2017-09-13 21:39
浏览 55
已采纳

如何使用PDO与依赖注入?

I'm having a hard time understanding how to use dependency injection. I've read over a lot of questions/answers here but I can't picture it with the code I'm using.

Model.php

abstract class Model {

    protected static function getDB() {
        static $db = null;

        if ($db === null) {
            $db = new PDO('mysql:host=host;dbname=dbname;charset=utf8', 'dbuser', 'password');
        }

        return $db;
    }
}

The model.php just contains that function, which I want to move away from setting and calling it statically.

User.php

class User extends Model {

    /*
    * Selects all of the user information
    */
    public function getUser($id){

        $db = static::getDB();

        $sth = $db->prepare('SELECT * FROM user WHERE id = :id');
        $sth->bindValue(':id', $id, PDO::PARAM_INT);
        $sth->execute();

        return $sth->fetch();
    }

    /*
    * Selects all of the user posts
    */
    public function getUserPosts($id){
        $db = static::getDB();

        $sth = $db->prepare('SELECT * FROM user_posts WHERE user_id = :id');
        $sth->bindValue(':id', $id, PDO::PARAM_INT);
        $sth->execute();

        return $sth->fetch();
    }
}

In the user.php I'm extending the model class, but I have set the $db = static::getDB(); in every single function.

I know that dependency injection is pretty much just passing the methods/variables to an object but I'm not even sure I'm doing this right.

Updated with further thoughts:

I'm thinking it would be better to create a private variable, and in the constructor we'd just call the getDB() like so:

class User extends Model {

    protected $db;

    public function __construct(){
        $this->db = getDB();
    }

    /*
    * example usage
    */
    public function getUser($id){
        $sth = $this->db->prepare('SELECT * FROM user WHERE id = :id');
        $sth->bindValue(':id', $id, PDO::PARAM_INT);
        $sth->execute();

        return $sth->fetch();
    }
}

But would it still count as dependency injection as I'm not calling the class directly in the function constructor?

SECOND UPDATE: After reading multiple guides, and this page which wound up making a lot more sense, this is what I came up with.

model.php

abstract class Model {
    protected $db = null;

    public function __construct(){
        if($this->db === null){
            try {
                $this->db = new PDO('mysql:host=' . Config::DB_HOST . ';dbname=' . Config::DB_NAME . '; charset=utf8', Config::DB_USER, Config::DB_PASSWORD);
                $this->db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
            } catch (PDOException $e) {
                echo 'Connection failed: ' . $e->getMessage();
            }
        }
        return $this->db;
    }
}

User.php

class User extends Model {

    protected $db;

    public function __construct(Model $db){
        $this->db = $db;
    }

    /*
    * example usage
    */
    public function getUser($id){
        $sth = $this->db->prepare('SELECT * FROM user WHERE id = :id');
        $sth->bindValue(':id', $id, PDO::PARAM_INT);
        $sth->execute();

        return $sth->fetch();
    }
}

How does that look?

  • 写回答

1条回答 默认 最新

  • douyinghuo8874 2017-09-13 22:48
    关注

    I think that you are not using Dependency Injection because you are not actually supplying any dependencies into your Model, you are generating them on the constructor.

    In order to supply the dependency you should pass it as an argument to the constructor:

    public function __construct($db){
        $this->db = $db;
    }
    

    This way you decouple the creation of the connection from your Class and you can use the benefits of Dependency Injection, like passing a Mock object for testing instead of the actual thing.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 执行 virtuoso 命令后,界面没有,cadence 启动不起来
  • ¥50 comfyui下连接animatediff节点生成视频质量非常差的原因
  • ¥20 有关区间dp的问题求解
  • ¥15 多电路系统共用电源的串扰问题
  • ¥15 slam rangenet++配置
  • ¥15 有没有研究水声通信方面的帮我改俩matlab代码
  • ¥15 ubuntu子系统密码忘记
  • ¥15 保护模式-系统加载-段寄存器
  • ¥15 电脑桌面设定一个区域禁止鼠标操作
  • ¥15 求NPF226060磁芯的详细资料