Interfaces Abstract Classes and the Adapter Pattern

By | 1st May 2011

PHP 5 made significant improvements on the Object Orientated programming model of PHP 4 bringing it more in line with languages such as Visual Basic .NET and Java. The improved object model in PHP 5 makes developing applications using OOP much easier and gives you the programmer, greater flexibility.

The first features new to PHP 5 to be covered in this article are abstract classes and interfaces. These concepts are nothing more than features added to OOP, which help the programmer follow good coding standards.

Abstract Classes

An abstract class is a class that is only partially implemented by the programmer. It may contain one or more abstract methods. An abstract method is simply a function definition that serves to tell the programmer that the method must be implemented in a child class.

An Abstract PHP class

<?php  
abstract class Weapon  
{  
    private $SerialNumber;  
    abstract public function fire();  

    public function __construct($SerialNumber)  
    {  
        $this->SerialNumber = $SerialNumber;  
    } 

    public function getSerialNumber()  
    {  
        return $this->SerialNumber;  
    }  
}  
?>
The fire() method however, cannot be implemented because each different weapons use different firing different mechanisms. The method is therefore declared as abstract, meaning it will be implemented in a more specific child class. 
Because the class is abstract, an instance of it can never be created (remember, it is only a partial implementation). Instead a child class must be created using inheritance and implement the fire method in itself. Failure to do so will result in a fatal error. Listing 2 shows a child class being created from the Abstract Weapon class.

Extending the Abstract Weapons class

<?php 
class Gun extends Weapon 

    public function fire() 
    { 
        if($this->SafetyOff) { 
            return $this->CurrentBullet; 
        } 
    } 

class Cannon extends Weapon 

    public function fire() 
    { 
        $this->NeedsLoading = true; 
        return $this->CurrentCanon; 
    } 
?>

An instance of the Cannon and Gun classes can now be created because they now fully implemented subclasses of weapon.

Interfaces
An interface is similar to an abstract class; indeed interfaces occupy the same namespace as classes and abstract classes. For that reason, you cannot define an interface with the same name as a class. An interface is a fully abstract class; none of its methods are implemented and instead of a class sub-classing from it, it is said to implement that interface.

An interface will be used in the database abstraction layer you create. This ensures that every time you create a class for a particular database, the same API is exposed. When using an interface, you can then rely on the methods defined for the interface to be part of the class because, if they are not, PHP will not parse it.

The MySql functions will be used as an example because they are the most commonly used amongst PHP programmers. The most commonly used functions are:

mysql_connect()
mysql_error()
mysql_errno()
mysql_query()
mysql_fetch_array()
mysql_fetch_row()
mysql_fetch_assoc()
mysql_fetch_object()
mysql_num_rows()
mysql_close()
If all the database class APIs you create can expose the same methods with the same return types then you can be sure that changing from one database to another, such as from MySql to Postgre SQL, will be painless. As such, the interface in Example can be determined for your API.

Abstracted Database Interface

interface DB
{
    public function connect();
    public function error();
    public function errno();
    public static function escape_string($string);
    public function query($query);
    public function fetch_array($result);
    public function fetch_row($result);
    public function fetch_assoc($result);
    public function fetch_object($result);
    public function num_rows($result);
    public function close();
}

Any class implementing the interface must define each method that is declared in the interface, and each method must have at least the parameters identified in their interface definitions. It may have more parameters as long as they are optional, but it cannot have less.

Implementing the database interface

class MySqlDB implements DB
    {
        private  $link;
        
        public function connect($server=”, $username=”, $password=”, $new_link=true, $client_flags=0)
        {
            $this->link = mysql_connect($server, $username, $password, $new_link, $client_flags);
        }
    
        public function errno()
        {
            return mysql_errno($this->link);
        }

        public function error()
        {
            return mysql_error($this->link);
        }

        public static function escape_string($string)
        {
            return mysql_real_escape_string($string);
        }

        public function query($query)
        {
            return mysql_query($query, $this->link);
        }
        
        public function fetch_array($result, $array_type = MYSQL_BOTH)
        {
            return mysql_fetch_array($result, $array_type);
        }

        public function fetch_row($result)
        {
            return mysql_fetch_row($result);
        }
        
        public function fetch_assoc($result)
        {
            return mysql_fetch_assoc($result);
        }
        
        public function fetch_object($result)
        {
            return mysql_fetch_object($result);
        }
        
        public function num_rows($result)
        {
            return mysql_num_rows($result);
        }
        
        public function close()
        {
            return mysql_close($this->link);
        }

Creating a database class

$db = new MySqlDb;
$db->connect(‘host’, ‘username’, ‘password’);
$db->query(‘use users’); // we could also use $db->select_db here but it is not consistent with the interface

$result = $db->query(“SELECT username FROM users”);

while($row = $db->fetch_assoc($reuslt)) {
echo($row[‘username’]);
}

Category: PHP

Leave a Reply

Your email address will not be published. Required fields are marked *