Abstraction en php 4

Abstraction en php 4

Introduction

Sous PHP 4 on a pas la possibilité de créer des interfaces ou des classes abstraites, ce qui perd un peu l'attrait de la POO. Une astuce dans ce cas ...
L'idée c'est de vous proposer de rationaliser le développement objet sous PHP 4 au cas où vous n'auriez pas le choix - sinon passez à PHP 5.
On commence tout d'abord par la définition d'une classe abstraite selon le WIKI :

Classe abstraite

Dans certains langages, une classe peut être partiellement définie. En particulier, certaines méthodes de cette classe n'ont pas de corps ou d'implémentation. Ces méthodes sont dites abstraites (ou virtuelles en C++).
Les classes possédant au moins une méthode abstraite sont aussi dites classes abstraites (ou virtuelles) et ne peuvent pas être instanciées directement -sauf en créant une sous-classe non abstraite.
Exemple : On souhaite modéliser les relations objets d'un dessin vectoriel. On peut dire qu'un objet dessin est un ensemble de géométries (la classe abstraite) et chaque géométrie peut être un point, un polygone ou une ligne brisée (ces trois classes héritent de géométrie). La classe abstraite n'est donc pas indispensable en soi, mais elle est indispensable[1] pour un modèle propre, générique et simplifié.
Le mixin est un cas particulier de classe abstraite. Il permet d'ajouter un service aux sous-classes.

Interface

Une classe ne possédant que des méthodes abstraites est appelée interface ou classe purement virtuelle (en C++) ou protocole (en Objective C).

Du coup, on comprend vite pk en PHP 4 si on veut faire de la POO cela devient indispensable.
La solution - c'est l'héritage et de créer une classe s'appelant abstractClass par exemple :

$GLOBALS['abstractClass' *  = array(); 
class abstractClass { 
    function abstractClass($methods) { 
        $class_name = get_class($this); 
        if (isset($GLOBALS['abstractClass' * [$class_name])) return true; 
        foreach($methods as $name => $args) $this->checkMethod($name); 
        $GLOBALS['abstractClass' * [$class_name] = $methods; 
    } 
    function triggerError($description) { 
        return trigger_error($description, E_USER_ERROR); 
    } 
    function checkMethod($name, $args = NULL) { 
        if (!method_exists($this, $name)) { 
            return $this->triggerError('You class '.get_class($this).' must implements '.$name.'('.$args.') function !'); 
        } else return true; 
    } 
    function abstractMethods() { 
        $class_name = get_class($this); 
        if (isset($GLOBALS['abstractClass' * [$class_name])) { 
            return $GLOBALS['abstractClass' * [$class_name] = $methods; 
        } else { 
            return $this->triggerError('abstractMethods is not a static method or '.$class_name.' is not a compliant class !'); 
        } 
    }                       
} 

Lors de la création de votre classe abstraite, faites-la hériter de abstractClass de la manière suivante :

class dbConnector extends asbtractClass { 
    function dbConnector() { 
        parent::asbtractClass(array( 
            'connect' => '$user, $pwd, $host', 
            'close' => '', 
            'request' => '$sql' 
            )); 
    } 
}

Lors de la construction de la classe appelez le constructeur de la classe parente en lui spécifiant un tableau composé en indice du nom de la fonction et en valeur de la liste de ses arguments (a titre indicatif).
Voici un exemple concret d'utilisation :

class mySqlConnector extends dbConnector { 
    function connect($user, $pwd, $host) { 
        // YOUR CODE 
    } 
    function request($sql) { 
        // YOUR CODE 
    } 
    // VOLUTARY FORGET CLOSE FUNCTION ... 
}   
$db = new mySqlConnector(); 
// OUTPUT ERROR : You class mySqlConnector must implements close() function !  

AVANTAGES

Vous pouvez avoir un gestionnaire d'erreurs qui vérifiera la conformité des définitions de votre classe concrète.
Votre classe abstraite ne pourra pas être construite directement.

DESAVANTAGES

La vérification se fait sur la construction de l'objet et non sur la définition de la classe - du coup l'erreur n'est visible que lors de l'instanciation de l'objet.
La vérification dans le constructeur s'effectue à chaque chargement, du coup baisse des perfs surtout si l'objet est chargé une multitude de fois.

CONSEILS

Méthode à utiliser que sur des classes abstraites qui devront être implémentées par des tiers sinon la vérification n'a pas trop d'importance, on part du principe que vous êtes au point sur votre propre architecture et que vous avez du temps pour débuguer en cas de problème.

Ce document intitulé « Abstraction en php 4 » issu de CodeS SourceS (codes-sources.commentcamarche.net) est mis à disposition sous les termes de la licence Creative Commons. Vous pouvez copier, modifier des copies de cette page, dans les conditions fixées par la licence, tant que cette note apparaît clairement.