PHP 将 PDO 对象传递到其他 Main 的好方法 类

PHP A Good way to pass the PDO Object into other Main classes

我是 PHP OOP 的新手,现在我很困惑是否有更好的方法来使用数据库 Class 然后将其扩展到所有数据库。

例如,我有 3 个主要 classes:EmployeeCustomerArticle。每个 classes 都有一个扩展形式的子 classes。到目前为止,我所做的是在这 3 个主要 class 中的每一个上扩展 Db class。

我的数据库class:

class DbController{
private $serverName;
private $userName;
private $userPass;
private $dbName;
private $charSet;
private $pdo;

protected function __construct() {
    try {
        $this->serverName   = "localhost";
        $this->userName     = "blabla";
        $this->userPass     = "***";
        $this->dbName       = "blabla";
        $this->charSet      = "utf8mb4";

        $dsn = "mysql:host=".$this->serverName."; dbname=".$this->dbName."; charset=".$this->charSet;
        $pdo = new PDO($dsn, $this->userName, $this->userPass);
        $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
        $this->pdo = $pdo;
        return $pdo;
    } catch (PDOException $err) {
        die($err->getMessage());
    }
}


protected function getPdo(){
    return $this->pdo;
}




public function __debugInfo(){
    $properties = get_object_vars($this);
    unset($properties['serverName']);
    unset($properties['userName']);
    unset($properties['userPass']);
    unset($properties['pdo']);
    unset($properties['dbName']);
    unset($properties['charSet']);

    return $properties;
}
}

主要 class 之一 (Employee):

<?php
if (session_status() === PHP_SESSION_NONE) {
    session_start();
}

include_once "DbController.cls.php";

class Employee{
public $id;
protected $name;
protected $username;
protected $scoore;
protected $dbTable = "employee";
protected PDO $pdo;

public function __construct($info = NULL) {
    // pls notice that The DbController() is a protected Constructor.
    $this->pdo = new DbController();
    if (isset($info)) {
        $this->id = $info["id"];
        $this->name = $info["name"];
        $this->username = $info["username"];
        $this->scoore = $info["scoore"]; 
    }
    
}

// Setters and Getters ......

然后 Employee 的子 class 叫做 EmployeeMng。这个 subclass 包含登录或注册等功能。此 subclass 还处理来自客户端的 POST 请求。

include_once "../classes/Employee.cls.php";
$_POST = json_decode(file_get_contents('php://input'), true);

class EmployeeManagement extends Employee{
public function __construct() {
    if (isset($_SESSION['empID'])) {
        parent::__construct();
        parent::__construct($this->fetchEmpInfo($_SESSION['empID']));
    } else {
        parent::__construct();
    }
}

public function signIn($username, $password){
    $retrunArray = array('code' => 0, 'msg' =>  "No Data Returned");
    $checkCredential = $this->checkCredential($username, $password);
    if ($checkCredential['code'] == 1) {
        try {
            $getEmpID = $this->pdo->prepare("SELECT `id` FROM `employee` WHERE `username`=? AND `password`=? LIMIT 1;");
            $getEmpID->execute([$username, $password]);
            $empId = $getEmpID->fetch(PDO::FETCH_ASSOC)['id'];

            $_SESSION['empID'] = $empId;

            $retrunArray['code'] = 1;
            $retrunArray['msg'] = "Erfolgreich eingeloggt";
            return $retrunArray;
            
        } catch (PDOException $err) {
            $retrunArray['code'] = 0;
            $retrunArray['msg'] = $err->getMessage();
            return $retrunArray;
        }
    } else{
        // In case of DB Error
        return $checkCredential;
    }
}

// Request Handler Begin
$employeeService = new EmployeeManagement();
header('Content-Type: application/json');

// Login:
if (isset($_POST["signIn"])) {
    $signIn = $employeeService->signIn($_POST["username"],     $_POST["password"]);
    echo json_encode($signIn);
}

现在我尝试在 Employee 构造函数中声明数据库 class。但我一直收到错误 Call to protected DbController::__construct() from scope Employee。有干净的方法吗?

通常,您会在此 class 之外创建数据库对象,然后将其作为参数注入。这叫做 Dependency Injection,是一件好事™。

然后您将在 class 特定方法中使用该参数。所以你的员工 class 看起来像这样:

class Employee
{
    protected $db;

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

    public function find($id)
    {
        // or whatever your query looks like
        $stmt = $this->db->query('SELECT * FROM EMPLOYEE WHERE id = :id');
        // $row = ...
        return $row;
    }

    public function getAll()
    {
        $stmt = $this->db->query('SELECT * FROM EMPLOYEE');
        // whatever
    }
}

然后要使用 class,您需要实例化一个数据库对象,然后将其传递给员工:

$db = new PDO();
$employee = new Employee($db);
$steve = $employee->find(1);

你应该这样做:

class Employee
{
    public $db;

    public function __construct(PDO $db)
    {
        $this->db = $db;
    }
}
$db = new PDO();
$employee = new Employee($db);
$steve = $employee->db->query('...');

或者这样:

class Employee extends PDO
{
    // ...
}
$employee = new Employee($db);
$employee->query('...');

继承不是解决问题的方法。如果您继承 DbController,每个 class 将实例化一个新的 PDO 连接。

相反,首先实例化 DbController,然后调用它的 getPDO() 方法来获取 PDO 连接对象以作为参数传递给其他 classes 的构造函数。您需要将 DbController 方法声明更改为 public 而不是 private

像这样:

class DbController{
private $serverName;
private $userName;
private $userPass;
private $dbName;
private $charSet;
private $pdo;

public function __construct() {
    try {
        $this->serverName   = "localhost";
        $this->userName     = "blabla";
        $this->userPass     = "***";
        $this->dbName       = "blabla";
        $this->charSet      = "utf8mb4";

        $dsn = "mysql:host=".$this->serverName."; dbname=".$this->dbName."; charset=".$this->charSet;
        $pdo = new PDO($dsn, $this->userName, $this->userPass);
        $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
        $this->pdo = $pdo;
        // return $pdo;  No need for this. The constructor doesn't use it.
    } catch (PDOException $err) {
        die($err->getMessage());
    }
}


public function getPdo(){
    return $this->pdo;
}
}

class Employee {
  private $PDO;
  public function __construct(PDO $pdo) {
    $this->PDO = $pdo
  }
  public function getEmployee($id) {
    // get employee details using $this->PDO as your connection object
  }
}

那么你的主程序就变成了

    require_once('DbController.php');
    require_once('Employee.php');
    $DB = new DbController();
    $emp = new Employee($DB->getPDO());
    $id = 'some employee reference';
    $employeeDetails = $emp->getEmployee($id);