I am learning some OOP on PHP and I have developed some sample code to practise. Ignoring the functionality, I just want to learn the "best" or "better" way to write OOP codes in PHP. The following is my code and I hope anyone who has been doing PHP can help to review or comment for any improvements or weaknesses on my code. I want to develop my style of code in which copy-and paste is minimum and functionality expandability is rich. For example, the `execute()` function in the `UserDB` class is basically the same function and can be used widespread in many diff db class. Do I need to copy and paste the code again or should I just moved this piece of code to abstract class? How can I optimized my code to made it better for future functionalities such as other select, insert, update and delete while maintaining readability and still within OOP standards? <?php require_once "sys_config.php"; require_once "general.inc"; $para[":user"]= "%"; $dataset = UserFactory::getUsers($para); var_dump($dataset); ?> **`UserFactory` class** <?php class UserFactory{ public static function getUsers($para) { $db = new UserDB("CALL getUsers(:user)",$para); //sp $objs = $db->execute(); if(!empty($objs)) foreach( $objs as $obj) { $users[] = new user($obj); } return $users; } } ?> **`UserDB` class** <?php Class UserDB extends Database{ protected $conn; protected $SQL; protected $para; function __construct($SQL, $para) { parent::__construct(); $this->conn = parent::getConn(); $this->SQL = $SQL; $this->para = $para; } function execute() { $query = $this->conn->prepare($this->SQL); if(!empty($this->para)) foreach($this->para as $key=>$val) { $query->bindParam($key,$val); } $results = $query->execute(); $dataset = null; if($results) { while($row = $query->fetch(PDO::FETCH_OBJ)) { $dataset[]=$row; } } unset($this->conn); parent::__destruct(); return $dataset; } } ?> **`Database` abstract class** <?php abstract Class Database{ protected $conn; function __construct() { $this->conn = new PDO ("mysql:host=".DB_LOCATION.";dbname=".DB_NAME,DB_USER,DB_PASS); } function __destruct() { unset($this->conn); } function getConn() { return $this->conn; } abstract function execute(); } ?> **`User` object class** <?php class User{ private $fullname; private $id; function __construct($userObj) { $this->fullname = $userObj->fullName; $this->id = $userObj->id; } function setFullname($fullname) { $this->fullname = $fullname; } function getFullname() { return $this->fullname; } function setId($id) { $this->id = $id; } function getId() { return $this->id; } } ?>