Abstract classes are useful when you want to keep a certain level of separation between your application components. Suppose that you have to work with multiple databases. In one project, you have a MySQL database and in another a PostgreSQL one. However, certain database operation are the same, such as connect and disconnect to and from a database. Basically, you need an abstract class which contains such common operations and a concrete one that extends the base abstract class. In this post, I'm going to show you how to accomplish this task.
First, the abstract class with some members:
abstract class Database { const DB_HOST = 'localhost'; const DB_NAME = 'site'; const DB_USER = 'user'; const DB_PWD = 'test'; abstract protected function connect(); abstract protected function disconnect(); }
So we have four constants with all the information needed to work with a database and two abstract methods that we're going to implement in our child class. To begin with, two things to keep in mind:
- to extend an abstract class, you don't have to use its constructor method or you'll get an error
- if you implement abstract methods, your child methods must have the same visibility of your parent methods or you'll get an error.
Here's an example:
class mySQL extends Database { protected $_connection; public function __construct() { $this->connect(); } protected function connect() { $this->_connection = mysql_connect(self::DB_HOST, self::DB_USER, self::DB_PWD); mysql_select_db(self::DB_NAME, $this->_connection); } protected function disconnect() { return @mysql_close($this->_connection); } public function __destruct() { $this->disconnect(); } protected function query($query) { if($results = mysql_query($query, $this->_connection)) { $rows = array(); while($result = mysql_fetch_array($results)) { $rows[] = $result; } return $rows; } else { return mysql_error($this->_connection); } } }
This child class can be further extended to display the results of a MySQL query:
class Displayer extends mySQL { public function __construct() { parent::__construct(); } public function display($queryResults) { $results = $this->query($queryResults); $html = ''; foreach($results as $result) { $html .= '<p>' . $result['post_content'] . '</p>' . "\n"; } return $html; } }
Finally, a practical use case:
$displayer = new Displayer(); $query = "select post_content from st_posts"; echo $displayer->display($query);