【问题标题】:PHP Recommend way to initiate database connection from Class Instance [closed]PHP推荐从类实例启动数据库连接的方法[关闭]
【发布时间】:2019-01-11 13:39:11
【问题描述】:

我在 PHP 中有以下类:

class Database {
    ...
}

class Product {
    public function __construct() {
        ...
    }
}

目前我正在考虑拥有一个数据库类的全局实例,其中在 Product 类的 __construct 方法中,我将检查对象是否已按如下方式初始化:

class Product {
    public function __construct() {
         if (!isset($db)) {
            throw new Exception ('Database object not initialized.');
        }
        ...
    }
}

这是一个好的实现吗?如果没有,你有什么推荐的?

【问题讨论】:

  • @tadman 您是否建议使用 ORM 来开发广泛的 Web 应用程序?
  • 建议进行更多研究,然后在需要时提出更具体的问题。这是一个很好的资源:@​​987654321@
  • 在我的项目Grumpy-Free-Framework 中,我可以在模型中执行此操作,方法是在声明包含数据库对象的变量后从我的基本实例中提取保存的数据库信息。

标签: php mysql database class oop


【解决方案1】:

在我看来,您正在尝试构建自己的 ORM 并且实践是好的。对于大型项目,为了更舒适,可以考虑采用一些 ORM,如 Doctrine、Eloquent 等(取决于框架)。

不使用依赖注入的方法可能需要在构造函数中实例化数据库对象本身。让我们举个例子,利用单例来提供 DB 对象。

class Product {
    private $pdo = null;
    // other product properties here

    public function __construct() {
        // get db
        try {
            // set PDO object reference on this object
            $this->pdo =  PDOSingleton::getInstance();
        } catch (Exception $e) {
            error_log('Unable to get PDO instance. Error was: ' .
                $e->getMessage();
            // perhaps rethrow the exception to caller
            throw $e;
        }
        // query DB to get user record
    }

    // other class methods
}

// example usage
$product = new Product(1);

当使用依赖注入时,它可能看起来像这样:

class Product {
    private $pdo = null;
    // other product properties here

    // pass PDO object to the constructor. Enforce parameter typing
    public function __construct(PDO $pdo) {
        $this->pdo = $pdo;
        // query DB to get product record
    }

    // other class methods
}

// example usage
// instantiate PDO object. This probably happens near beginning
// of code execution and might be the single instance you pass around
// the application
try {
    $pdo = new PDO(...);
} catch (PDOException $e) {
    // perhaps log error and stop program execution
    // if this dependency is required
}

// somewhere later in code
$product = new Product($pdo);

这似乎只是一个细微的区别,但使用这种方法的开发人员喜欢它,因为它:

  • 将消费类与如何实例化依赖项的细节分离。为什么用户类必须知道要使用哪个单例才能获得它的 PDO 依赖关系?所有类应该关心的是知道如何使用依赖项(即它具有哪些属性和方法),而不是如何创建它。这更接近于 OOP 中通常需要的单一职责原则,因为用户类只需要处理实例化用户表示,而不必实例化其依赖项。

  • 消除了需要依赖项的类之间的重复代码,因为您不需要在每个类中围绕实例化/创建依赖项进行所有处理。在示例代码中,我消除了在构造函数中可能处理失败的 DB 实例化的需要,因为我知道我已经有一个有效的 PDO 对象作为参数传递(如果我没有传递一个,我会得到无效的参数异常)。

【讨论】:

  • 参考第二种形式,我想要避免每次实例化 Product 类时都必须传递数据库实例。如果我在包含在所有页面上的头文件中有一个数据库类的实例,并在 Product 类的构造函数中使用 global $db; 怎么办?
猜你喜欢
  • 2012-10-29
  • 2011-06-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多