首页 > 解决方案 > 如何将数据库传递给类?

问题描述

我正在使用此处https://www.sitepoint.com/front-controller-pattern-1/找到的前端控制器模式。因此,我的应用程序中的所有类都是在我页面上的run()函数中创建的:index.php

$frontController = new FrontController();
$frontController->run();

我正在通过 PDO 访问我的数据库$dbh = new PDO('mysql:host='.$host.';dbname='.$database, $user, $pass);

我的问题是我不知道如何将数据库传递给 FrontController 创建的对象。

我尝试将数据库传递给 FrontController,然后将其传递给 FrontController 中的类。简化示例如下所示。

$dbh = new PDO('mysql:host='.$host.';dbname='.$database, $user, $pass);

class FrontController {

    const DEFAULT_CONTROLLER = "IndexController";
    const DEFAULT_ACTION     = "index";
    
    protected $controller    = self::DEFAULT_CONTROLLER;
    protected $action        = self::DEFAULT_ACTION;
    protected $params        = array();
    protected $basePath      = "";
    protected $dbh;

    public function __construct($dbh, array $options = array()) {
        $this->dbh = $dbh;
        if (empty($options)) {
           $this->parseUri();
        }
        else {
            //set controller, action and params
        }
    }

    public function run() {
        call_user_func_array(array(new $this->controller($this->dbh), $this->action), $this->params);
    }
}

class User {
    
    public $dbh;

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

    function get_username_from_db(){
        $stmt = $this->dbh->prepare(...);
        //etc
}

索引.php

$frontController = new FrontController($dbh);
$frontController->run();

上面的代码有效,但感觉很笨拙。FrontController 仅用于路由应用程序,永远不会访问数据库本身。因此,它不需要知道该$dbh对象,除非它会创建其他需要知道$dbh该类的对象。这也意味着如果 FrontController 创建了另一个不需要$dbh该类的对象,该对象无论如何都会获得该类,因为 FrontController 正在向每个人$dbh传递一个副本。$dbh

我的问题是:是否有一种更简洁的方法可以将数据库传递给 FrontController 创建的对象,以便只有需要它的对象才能获得它,并且只有在他们需要它的时候才能获得它?我正在尝试遵循最佳实践/基本原则,但我在本网站或其他地方找不到任何反映这种情况的问题。据我所知,这是正确的做法,但我怀疑不是。

标签: phpdatabasepdodependency-injection

解决方案


您可以将数据库调用包装在这样的类中。

class database {
   function connect(){
      $dbh = new PDO('mysql:host='.$host.';dbname='.$database, $user, $pass);
      return $dbh;
   }
}

那么,如果你只需要函数 run中的数据库,你可以这样做

class FrontController {
//.....
function run(){
    $dbh = (new database)->connect();
  //...
}
}

对于用户类,您可以使用已使用的用户,也可以使用以下代码。

class User {
    
    public $dbh;

    function __construct(){
        $this->dbh = (new database)->connect();
    }

    function get_username_from_db(){
        $stmt = $this->dbh->prepare(...);
        //etc
}

推荐阅读