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('...');