2010-08-13 18 views
0

Je travaillais sur une classe abstraite pour économiser du code sur quelques classes. Ces classes sont toutes des usines qui s'instancient à travers différents appels statiques. Je pourrais sauver du code en mettant toutes ces méthodes dans une classe abstraite.Résumé Les usines ne sont pas possibles en PHP <5.3?

Cependant, j'ai rencontré un problème de liaison statique tardive ... étant donné que notre hébergeur n'utilise pas la version 5.3 ou ultérieure, je n'ai pas accès à get_called_class. Si j'ai dans la classe abstraite

$class = __CLASS__; 
return new $class(); 

, __CLASS__ est le nom de la classe abstraite, quand je veux réellement utiliser la classe appelée. J'ai vu des exemples d'usines abstraites sur le web où les classes enfants ont leurs propres méthodes d'instanciation, et ne comptent pas sur le parent abstrait pour cela. Cependant, dans cette situation, la seule raison de la classe abstraite est de sauvegarder le code, donc si je ne peux pas le faire, la valeur de celle-ci diminue grandement.

Y a-t-il une solution de contournement dans PHP < 5.3? debug_backtrace()?


Edit:

j'ai fait un test et il semble debug_backtrace() ne fonctionnera pas! Je suppose que c'est pourquoi nous avons besoin liaison statique tardive.

<? 

abstract class abstractFactory { 
    public function create() { 
      print_r(debug_backtrace()); 
      $class = __CLASS__; 
      return new $class(); 
    } 
} 

class concreteFactory extends abstractFactory {} 

$chimborazo = concreteFactory::create(); 

et le résultat:

$ php test.php 
Array 
(
    [0] => Array 
     (
      [file] => /var/www/test.php 
      [line] => 13 
      [function] => create 
      [class] => abstractFactory 
      [type] => :: 
      [args] => Array 
       (
       ) 

     ) 

) 

Fatal error: Cannot instantiate abstract class abstractFactory in /var/www/test.php on line 7 

Répondre

0

Une fois façon de le faire est de passer outre les différentes méthodes d'instanciation, et de transmettre le nom de la classe directement:

<? 

abstract class abstractFactory { 

    public function create($class) { 
     return new $class(); 
    } 

    public function instantiate($class) { 
     return new $class(); 
    } 

} 

class concreteFactory extends abstractFactory { 

    public function create() { 
     parent::create(__CLASS__); 
    } 

    public function instantiate() { 
     parent::instantiate(__CLASS__); 
    } 
} 


$chimborazo = concreteFactory::create(); 
$chimborazo = concreteFactory::instantiate(); 
+0

Il n'utilise pas 5.3, donc il n'a pas le '__CLASS__ 'constant pour commencer ... – Charles

+0

Je suis l'OP;)' __CLASS__' est disponible depuis la version 4.3: http://php.net/manual/fr/language.constants.predefined.php. J'utilise 5.2.6 et je l'utilise tout le temps. – user151841

+0

J'ai besoin d'apprendre à lire, hein. – Charles

1

La seule solution que je l'ai vu pour cela implique d'appeler debug_backtrace pour déterminer le nom de la classe de l'appelant (s). Ceci est bien sûr un hack géant. J'ai vu un code qui combine un backtrace avec ouvrant réellement le fichier appelant et l'analysant pour comprendre les choses. Bizarre, truc horrible.

Le manque de LSB va revenir et vous mordre plus tard. Mettez à niveau maintenant, même si cela signifie changer d'hôte. En fait, surtout si cela signifie changer d'hôte. 5.3 est sorti depuis un an maintenant.

+0

Je l'ai fait un test, et d'appeler 'debug_backtrace()' dans le abstrait 'créer () 'la propriété n'avait pas d'élément référençant la classe d'origine! Je pense qu'il serait là, mais je suppose que c'est pourquoi nous avons besoin de liaison statique tardive: P – user151841

+0

Vérifiez le code de m1tk4 puis, il pourrait être plus intelligent ... – Charles

1

Voici ce que je l'ai utilisé jusqu'à passer à 5.3:

if (!function_exists('get_called_class')) { 

    /** 
    * Implementation of get_called_class() for pre-5.3 PHP 
    * 
    * @return string 
    */ 
    function get_called_class() 
    { 
     $bt = debug_backtrace(); 
     $lines = file($bt[1]['file']); 
     preg_match('/([a-zA-Z0-9\_]+)::'.$bt[1]['function'].'/', 
       $lines[$bt[1]['line']-1], 
       $matches); 
     return $matches[1]; 
    } 
} 

Cela vous permet de déterminer dans une fonction statique quel nom de classe la fonction a été invoquée avec. C'est une solution de contournement qui pose des problèmes de performances mais c'est la seule que j'ai trouvée. S'il y en a d'autres que j'aimerais savoir.