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

    ?>