Auteur: Ludovic PATEY

Publié le 7 avril 2008

Modifié le: 12 mai 2008

Page d'accueil

Réaliser un Bean en PHP

Vous êtes ici : Accueil / Articles / Formations en PHP

Qu’est-ce qu’un Bean ?

Un Bean est une classe devant respecter les conditions suivantes :

- Chaque propriété est en private
- Chaque propriété possède un accesseur et un manipulateur
- Le Bean doit posséder un constructeur sans argument.

Implémentation explicite

Voici une première implémentation en PHP, de manière explicite. L’avantage de cette syntaxe est la lisibilité. En revanche, pour chaque Bean, il est nécessaire de redéfinir toutes les méthodes, ce qui est fastidieux :

<?php
class HumanBean {

       private $first_name;
       private $last_name;

       /*
       * Le constructeur par defaut n'a pas d'argument
       */



       /*
       * Manipulateurs
       */

       public function setFirstName( $first_name ) {
               $this->first_name = $first_name;
       }

       public function setLastName( $last_name ) {
               $this->last_name = $last_name;
       }

       /*
       * Accesseurs
       */

       public function getFirstName( $first_name ) {
               return $this->first_name;
       }

       public function getLastName( $last_name ) {
               return $this->last_name;
       }
}
?>

Une solution générique

PHP, à la différence de Java, permet de définir des propriétés et méthodes "à la volée", grâce à sa réflexivité. Nous allons donc définir une classe parent Bean dont hériteront tous les beans. Pour cela, nous auront recours à la méthode suivante :

<?php
public function __call( $name, $args )
?>

Cette méthode est appelée lors de l’appel à une méthode n’existant pas. Ainsi, si nous créons une classe sans méthode et que nous tentons d’en appeler une, cette méthode sera appelée à la place, prenant en premier paramètre le nom de la méthode que l’on voulait appeler, et en second un tableau des arguments.

Exemple :

<?php
class SansMethode {

       public function __call( $name, $args ) {
               echo "La méthode $name a été appelée";
       }
}

$o = new SansMethode();

// Affiche "La méthode setFirstName a été appelée"
$o->setFirstName( 'Robert' );
?>

Nous auront également recours à une expression régulière toute simple pour remplacer la syntaxe setFirstName en first_name :

<?php
// Transforme setFirstName en set_First_Name
$str = preg_replace( '/[A-Z]/', '_$0', $str );

// Transforme set_First_Name en set_first_name
$str = strtolower( $str );

// Transforme set_first_name en first_name
$str = substr( $str, 4 );
?>

Nous allons nous créer 2 méthodes de test : isSetter et isGetter, pour différencier les manipulateurs des accesseurs :

<?php
class Bean {

       private function isGetter( $name ) {
               return substr( $name, 0, 3 ) == 'get';
       }

       private function isSetter( $name ) {
               return substr( $name, 0, 3 ) == 'set';
       }

}
?>

Pour ne pas pouvoir accéder aux propriétés - définies à la volée - de l’extérieur de la classe, nous allons les stocker dans une propriété privée sous forme de tableau :

<?php
class Bean {

       private $prop = array();
}
?>

Il ne nous reste plus qu’à définir la méthode __call :

<?php
class Bean {

       private $prop = array();

       public function __call( $name, $args ) {

               // Si nous avons getMaVariable
               if( $this->isGetter( $name ) ) {
                       // Retourne $this->prop[ 'ma_variable' ]
                       return $this->prop[ $this->toProperty( $name ) ];
               }
               // Si nous avons setMaVariable( $valeur )
               else if( $this->isSetter( $name ) ) {

                       // Stocker la valeur dans $this->prop[ 'ma_variable']
                       return $this->prop[ $this->toProperty( $name ) ] = $args[0];
               }

       }

       private function isGetter( $name ) {
               return substr( $name, 0, 3 ) == 'get';
       }

       private function isSetter( $name ) {
               return substr( $name, 0, 3 ) == 'set';
       }

       private function toProperty( $name ) {

               // Transforme setFirstName en set_First_Name
               $str = preg_replace( '/[A-Z]/', '_$0', $str );

               // Transforme set_First_Name en set_first_name
               $str = strtolower( $str );

               // Transforme set_first_name en first_name
               $str = substr( $str, 4 );

       }

}
?>

Nous pouvons désormais écrire le code suivant :

<?php
$b = new Bean();

$b->setFirstName( 'Robert' );

echo $b->getFirstName();
?>

L’avantage est que toute les classes qui hériteront de la classe Bean pourront utiliser cette syntaxe sans redéfinir les méthodes, donc les gains de productivité sont indéniables. En revanche, la lisibilité en est amoindrie.

Commentaires

Jérôme a dit le 28 août 2009

Au secours ! T’as raison ! C’est vraiment trop fastidieux ! ;) On se demande vraiment pourquoi on a inventé l’objet ! :) Franchement, on croit rêver !
Change ton IDE, t’auras plus à te creuser les méninges pour rien ! :) Finalement, je l’aime mon Visual Studio :)

Auteur :

Message :