Pergunta

Eu tenho a estrutura básica atual para cada objeto de domínio que eu preciso para criar:

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;
    }
}

I inicialmente tentou refazer os métodos estáticos para a classe LP_Model pai só para aprender, finalmente, o que significa no mundo do php "ligação tardia estático".

Eu só estou querendo saber se alguém tem sugestões sobre como refatorar esse código para que eu não tenho redeclare as mesmas três funções em cada objeto de domínio que eu crio?

Foi útil?

Solução

Como sobre isto:

<?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";

?>

Infelizmente, para fazer as funções fáceis de chamada, você tem que duplicar get() e getCollection() em cada subclasse. A outra opção é para chamar a função na classe pai:

$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";

Você pode mudar o nome da classe base e seus nomes de função, se você quiser ir por esse caminho. Mas o ponto é que você deve nomear a classe filha em um lugar ou outro : ou fazer uma função clichê na classe filho como no meu primeiro exemplo, ou o nome da pessoa a classe em uma string como em meu segundo exemplo.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top