继承自 Db class - 两个数据库连接 | PHP

Inheriting from Db class - Two databases connection | PHP

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

所以我不想创建单独的 Db class 来做同样的事情,我想用与数据库相关的参数调用那个 Db class。

问题是,当我尝试使用 class 扩展 Db class 并向应用程序提供方法时,数据库连接未建立 - 它为空。

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

Class Main 扩展了 Db; Class 用户扩展数据库;

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

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*/
    }

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

谢谢!

编辑:

按照建议更新我的代码后,我在访问数据库连接 属性 时遇到问题,因此我无法在 Main 和 User class 中进行查询。

真正让我困惑的是 属性 它对 Main class 不可见的原因?

主要 class 方法严重依赖于数据库 link,我不确定如何解决这个问题..

更新代码:

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
        )

)

编辑2: 解决方法是将 prepare 方法添加到 DB.php,我能够成功执行查询。

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

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

@u_mulder正确描述了您面临的技术问题。 parent Db 构造函数不会从 child 构造函数中自动调用。您可以尝试通过显式调用 parent 构造函数来解决此问题:

class Main extends DB 
{

    public function __construct() 
    {
        parent::__construct();
    }
    // ...
}

问题是您的 parent (DB) 的构造函数需要参数,因此您还必须将这些参数传递给 child:

class Main extends DB 
{

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

但这没有任何意义。你最大的问题是设计。相反,您应该 favor composition of objects over inheritance,尤其是在这种情况下。尝试像这样重组您的 class:

class Main 
{
    protected $db;

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

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

并为您的 User class 做同样的事情。当您这样做时,您的 protected $link 属性 将不再在您的 Main class 中可见。这没关系,因为,实际上,您的 MainUser classes 不应该 看到那个 属性 因为什么是有一个 Db class 的意义何在?您可以通过向您的 Db class(例如 public function query($sql, $parameters))添加一些 public 方法来解决这个问题,然后从您的 MainUser classes.

一旦你开始工作,我建议你查看已经可用的Active Record Pattern, or look into scrapping your approach altogether in favor of incorporating one of the many open source ORMs