2008-12-24 15 views
4

I ont la structure de base actuelle pour chaque objet de domaine que je dois créer:refactoring pour supprimer le code des méthodes statiques Odeur

class Model_Company extends LP_Model 
{ 
    protected static $_gatewayName = 'Model_Table_Company'; 
    protected static $_gateway; 
    protected static $_class; 

    public static function init() 
    { 
     if(self::$_gateway == null) 
     { 
      self::$_gateway = new self::$_gatewayName(); 
      self::$_class = get_class(); 
     } 
    } 

    public static function get() 
    { 
     self::init(); 

     $param = func_get_arg(0); 

     if($param instanceof Zend_Db_Table_Row_Abstract) 
     { 
      $row = $param; 
     } 
     elseif(is_numeric($param)) 
     { 
      $row = self::$_gateway->find($param)->current(); 
     } 

     return new self::$_class($row); 
    } 

    public static function getCollection() 
    { 
     self::init(); 

     $param = func_get_arg(0); 

     if($param instanceof Zend_Db_Table_Rowset_Abstract) 
     { 
      $rowset = $param; 
     } 
     elseif(!$param) 
     { 
      $rowset = self::$_gateway->fetchAll(); 
     } 

     $array = array();  

     foreach ($rowset as $row) 
     { 
      $array[] = new self::$_class($row); 
     } 

     return $array; 
    } 
} 

J'ai essayé d'abord de factoriser les méthodes statiques dans la classe LP_Model mère pour apprendre enfin ce que signifie "liaison statique tardive" dans le monde php. Je me demande simplement si quelqu'un a des suggestions sur la façon de refactoriser ce code afin que je n'aie pas à redéclarer les trois mêmes fonctions dans chaque objet de domaine que je crée?

Répondre

3

Que diriez-vous ceci:

<?php 

abstract class Model_Abstract 
{ 
    protected $_gatewayName = null; 
    protected $_gateway = null; 

    protected function _init() 
    { 
     $this->_gateway = new $this->_gatewayName(); 
    } 

    protected function __construct($row = null) 
    { 
     $this->_init(); 
     if ($row) { 
      $this->_data = $row; 
     } 
    } 

    public static function getAbstract($class, $param) 
    { 
     $model = new $class(); 
     if($param instanceof Zend_Db_Table_Row_Abstract) 
     { 
       $row = $param; 
     } 
     elseif(is_numeric($param)) 
     { 
       $row = $model->_gateway->find($param)->current(); 
     } 

     return new $class($row); 
    } 

    public static function getAbstractCollection($class, $param = null) 
    { 
     $model = new $class(); 
     if($param instanceof Zend_Db_Table_Rowset_Abstract) 
     { 
       $rowset = $param; 
     } 
     elseif($param === null) 
     { 
       $rowset = $model->_gateway->fetchAll(); 
     } 

     $array = array(); 

     foreach ($rowset as $row) 
     { 
       $array[] = new $class($row); 
     } 

     return $array; 
    } 

    abstract public static function get($param); 
    abstract public static function getCollection($param = null); 
} 

class Model_Company extends Model_Abstract 
{ 
    protected $_gatewayName = 'Model_Table_Company'; 

    public static function get($param) { 
     return self::getAbstract(__CLASS__, $param); 
    } 

    public static function getCollection($param = null) { 
     return self::getAbstractCollection(__CLASS__, $param); 
    } 
} 

class Model_Table_Company extends Zend_Db_Table_Abstract 
{ 
    protected $_name = 'company'; 
} 

$model = Model_Company::get(1); 
print "Got an object of type ".get_class($model)."\n"; 

$models = Model_Company::getCollection(); 
print "Got ".count($models)." objects of type ".get_class($models[0])."\n"; 

?> 

Malheureusement, pour rendre les fonctions faciles à appeler, vous devez dupliquer get() et getCollection() dans chaque sous-classe. L'autre option est d'appeler la fonction dans la classe parente:

$model = Model_Abstract::getAbstract('Model_Company', 1); 
print "Got an object of type ".get_class($model)."\n"; 

$models = Model_Abstract::getAbstractCollection('Model_Company'); 
print "Got ".count($models)." objects of type ".get_class($models[0])."\n"; 

Vous pouvez renommer la classe de base et ses noms de fonction si vous voulez aller dans cette voie. Mais le point est que vous devez nommer la classe enfant dans un endroit ou l'autre: soit faire une fonction passe-partout dans la classe enfant comme dans mon premier exemple, ou bien nommer la classe dans une chaîne comme dans mon deuxième exemple.

+0

Merci encore une fois Bill. Je sais que vous avez mentionné la liaison statique tardive dans une réponse précédente, mais ce n'est que lorsque j'ai commencé à refactoriser le code que j'ai réalisé quelles étaient les implications de cette limitation. En regardant votre première solution, cela semble assez intuitif. –

+0

Et tandis que l'héritage parmi les propriétés statiques et les méthodes serait la solution la plus élégante, au moins maintenant les méthodes get et getCollection dans chaque classe sont limitées à une seule ligne de code par opposition à beaucoup de code dupliqué. –