从Db类继承-两个数据库连接| PHP


Inheriting from Db class - Two databases connection | PHP

在我的应用程序中,我只使用一个数据库,我创建了一个类来提供一些常用的方法。现在我需要实现额外的数据库。

所以我不想创建单独的Db类来做同样的事情,我想用Db相关的参数来调用这个Db类。

问题是,当我试图扩展Db类与类,我提供的方法应用程序,数据库连接不建立-它是空的。

Main和User都使用不同的数据库。

类扩展Db;

为什么这样的东西不起作用?

class Db {
    protected $link;
    private $host;
    private $user;
    private $pass;
    private $dbName;
    public function __construct($host, $user, $pass, $db) {
        $this->host = $host;
        $this->user = $user;
        $this->pass = $pass;
        $this->dbName = $db;
        $this->connect();
    }
public function connect() {
        try
        {
            $this->link = new PDO("mysql:host=" . $this->host .
                    ";dbname=" .  $this->dbName . ";charset=utf8mb4",  $this->user,  $this->pass );
            $this->link->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
            $this->link->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
        } catch (PDOException $exc)
        {
            $this->setMessage($exc->getMessage());
        }
    }
}
$db = new Db(HOST, USER,PASS,DB)
class Main extends DB {
    public function __construct() {
    }
    /** App methods bellow*/
    }
$db2 = new Db(HOST2,USER2,PASS2,DB2);
class User extends DB {
    public function __construct() {
    }
    /** App methods bellow*/
    }

实现两个不同的数据库连接的最简单的解决方案是什么?

谢谢!

<标题>编辑:

按照建议更新我的代码后,我有访问DB连接属性的问题,所以我不能在Main和User类中进行查询。

真正让我困惑的是,为什么这个属性对Main类不可见?

主类方法严重依赖于db链接,我不知道如何解决这个问题。

更新代码:

class Main {
    protected $db;
    public function __construct($db) {
        $this->db = $db;
    }
public function showFreeSlotsPerPlan() {
        try
        {
            $SQL = "some query";
            $stmt = $this->db->prepare($SQL);
 /** Prepared statements bellow **/
    }
    }
class Db {
    protected $link;
    private $host;
    private $user;
    private $pass;
    private $dbName;
    public function __construct($host, $user, $pass, $db) {
        $this->host = $host;
        $this->user = $user;
        $this->pass = $pass;
        $this->dbName = $db;
        $this->connect();
    }
    }

并按建议调用:

$db = new Db(HOST, USER, PASS, DB);
$main = new Main($db);

如果我尝试调用一个方法f.e. showFreeSlotsPerPlan()

Fatal error: Call to undefined method Db::prepare() in /var/www/html/Master/class/Main.class.php 

然后当我调试Main实例时,我得到以下内容:

Main Object
(
    [db:protected] => Db Object
        (
            [link:protected] => PDO Object
                (
                )
            [host:Db:private] => localhost
            [user:Db:private] => root
            [pass:Db:private] => password
            [dbName:Db:private] => dbname
        )
)

Edit2:解决方法是将prepare方法添加到DB.php中,并且我能够成功执行查询。

我仍然不确定这是最好的方法。我承认我的设计一点也不好。

public function prepare($sqlQuery) {
    return $this->link->prepare($sqlQuery);
}

@u_mulder正确地描述了您所面临的技术问题。父Db构造函数不会从子构造函数中自动调用。您可以尝试通过显式调用父构造函数来绕过这个问题:

class Main extends DB 
{
    public function __construct() 
    {
        parent::__construct();
    }
    // ...
}

问题是,你的父(DB)需要参数到它的构造函数,所以你也必须传递这些到你的孩子:

class Main extends DB 
{
    public function __construct($host, $user, $pass, $db) 
    {
        parent::__construct($host, $user, $pass, $db);
    }
    // ...
}

但是这没有意义。你最大的问题是设计。相反,您应该倾向于组合对象而不是继承,尤其是在这种情况下。试着像这样重构你的类:

class Main 
{
    protected $db;
    public function __construct($db) 
    {
        $this->db = $db;
    }
    // ...
}
$mainDb = new Db(HOST, USER,PASS,DB)
$main = new Main($mainDb);

对你的User类做同样的事情。当你这样做时,你的protected $link属性将不再在你的Main类中可见。这是可以的,因为,真的,您的MainUser不应该具有该属性的可见性,因为无论如何,拥有Db类的意义是什么?你可以通过添加一些公共方法到你的Db类(例如public function query($sql, $parameters)),然后从你的MainUser类调用。

一旦您开始工作,我建议您研究活动记录模式,或者考虑完全放弃您的方法,以支持合并已经可用的许多开放源码orm之一。