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