Skip to content
Advertisement

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

im new to PHP OOP, now i was woundering if there is a better way to use the Database Class then just extending it over all.

For Example i am having 3 main classes: Employee, Customer, Article. each of this classes have a subclasses which extends form. what i have done until now is extand the Db class on each of these 3 main classes.

My DB 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;
}
}

one Of the Main classes (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 ......

then there is a sub class of Employee called EmployeeMng. this subclass contains functions such as login or signup. also this subclass handles the POST requests coming froom the client side.

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);
}

Now i tried to declare the db class in the Employee constructor. but i keep getting the error Call to protected DbController::__construct() from scope Employee. is there a clean way to do that?

Advertisement

Answer

In general, you’d create your database object outside of this class and then inject it as a parameter. This is called Dependency Injection and is a Good Thing™.

Then you’d use that parameter within your class-specific methods. So your employee class would look something like this:

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

And then to use that class, you’d instantiate a database object, and then pass that to the Employee:

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

You should not do this:

class Employee
{
    public $db;

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

Or this:

class Employee extends PDO
{
    // ...
}
$employee = new Employee($db);
$employee->query('...');
User contributions licensed under: CC BY-SA
9 People found this is helpful
Advertisement