Results 1 to 7 of 7

Thread: Tutorial: PHP 5 OOP

Threaded View

  1. #2

    Thread Starter
    VBA Nutter visualAd's Avatar
    Join Date
    Apr 2002
    Location
    Ickenham, UK
    Posts
    4,906

    Interfaces Abstract Classes and the Adapter Pattern

    Interfaces Abstract Classes and the Adapter Pattern

    The first feature we will visit which is new to PHP 5, is abstract classes and interfaces. These concepts are nothing more than features added to OOP which force the programmer to follow good coding standards.

    Abstract Classes
    An abstract class is a class which is only partially implemented by the programmer. It may contain 1 or more abstract methods. An abstract method is simply a function definition and serves to tell the programmer that the method must be implemented in a child class. To create an abstract class we use the following:
    PHP Code:
    <?php
    abstract class Weapon
    {
        private 
    $SerialNumber;
        abstract public function 
    fire();

        public function 
    __construct($SerialNumber)
        {
            
    $this->SerialNumber $SerialNumber;
        }
        public function 
    getSerialNumber()
        {
            return 
    $this->SerialNumber;
        }
    }
    ?>
    The above abstract class contains some of the methods required for a weapon, but, the fire method cannot be implemented because each different weapon fires using a different mechanism. We therefore declare this as abstract. Because the class is abstract an instance of it can never be created (remember, it is only a partial implementation), instead we must create a child class using inheritance and implement the fire method in the subclass, failure to do so will result in a fatal error.
    PHP Code:
    <?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;
        }
    ?>
    We can now create an instance of the Cannon and Gun classes because they now fully implemented subclasses of weapon.

    Interfaces
    An interface is similar to an abstract class, indeed the occupy the same namespace as classes and abstract classes, (hence you cannot define an interface with the same name as a class). An interface however, is a fully abstract class; none of its method are implemented and, instead of a class subclassing from it; it is said to implement that interface.

    We are going to use an interface in our database abstraction layer, to ensure that every time we create a class for a particular database, it exposes the same API. When using them, we can then rely on the methods defined in the interface being part of the class, because, if they are not, PHP will not parse it.

    We are going to take the MySql functions as an example as it is the most commonly used database 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 our database classes expose the same methods with the same return types we can be sure that changing from MySql to Postgre SQL will be painless. We therefore arrive at the following interface:
    PHP Code:
    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();

    Each method declared in the interface must be defined by any class which implements it having at least the parameters identified. It may have more parameters (as long as they are optional), but it cannot have less. So let us look at a class which implements the DB interface. Didn't I mention something called the adapter pattern in the title? Yes, I did. Well, this is it – the adapter pattern is used by programmers in order to adapter one API to another using the original API. The API we are adapting from could be another object based API or like we are doing an adaption from a modular API. If you want to read more about the adapter pattern, you can find a more detailed explanation here.

    Notice how we have included an escape_string() method as a static method. This method does not require an active connection to a database and should not require and instance of any object which implements the DB interface. In my opinion, this is the single most important method of any database implementation; an poorly implemented escape string method could make your applications vulnerable SQL injection.

    PHP Code:
        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);
            } 
    You'll notice that there are many more mysql functions than we have adapted. However, this small subset of functions are sufficient to meet the needs of most applications which require trivial data storage an retrieval. The additional functions can be implemented and I have done this in the example file attached, you may also choose to add additional functionality to the class and the interface.

    PHP Code:
        $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']);
        } 
    You can now create a class for each database you want and as long as it implements the DB interface, switching from one to another is as easy as changing one line of code:
    PHP Code:
       $db = new MsSqlDb
    Conclusion

    In this article you have seen how to protect and restrict the visibility of object data using the accessibility modifiers private, protected and public when declaring class variables. These modifiers are used in the MysqlDB and DBQuery classes to protect data important to the internal workings of the objects.

    In our next article I'll present another new feature in PHP 5, type hinting. You will also get to extend the DBQuery to allow for support of all the functions in the DB interface that operate on the result of an executed query. This will be accomplished using delegation.

    If you have any comments regarding this tutorial please post them here, not in this thread.
    Attached Files Attached Files
    Last edited by visualAd; Apr 24th, 2006 at 12:13 AM.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width