Pergunta

Eu sou relativamente novo para programação orientada a objeto. Eu praticamente compreender os conceitos, mas em termos práticos, eu estou tendo um momento muito difícil encontrar informações sobre como melhor utilizar modelos em minhas aplicações Zend Framework.

Especificamente, eu tenho um modelo (que não se estende qualquer coisa) que não usa uma tabela de banco de dados. Ele usa getters e setters para acessar seus membros protegidos. Encontro-me lutando com a melhor forma de exibição deste modelo na vista. Eu não quero lógica em meus modelos de visão, mas eu me encontro na seguinte situação:

No meu controlador:

$object = new Object();
$object->setName('Foo Bar');
$this->view->object = $object;

Na minha modelo de visão:

<h2><?= $this->object->getName() ?></h2>

Eu realmente não gosto de chamar funções em meus modelos de visão, mas eu não sei a melhor maneira de fazer isso. Eu não quero que os membros do meu modelo a ser público, mas eu basicamente deseja alcançar os mesmos resultados:

<h2><?= $this->object->name ?></h2>

Eu não quero que meu controlador para fazer todo o trabalho de ter que saber tudo sobre o modelo:

$object = new Object();
$object->setName('Foo Bar');
$this->view->object = $object;
$this->view->object->name = $object->getName();

Qual é a melhor prática de utilização de modelos no Zend Framework? Alguém pode recomendar qualquer tutorial que iria me ajudar a entender este dilema Model / View no Zend Framework?

Foi útil?

Solução

Uma possibilidade é usar o __set magia e __get métodos em PHP. Eu usá-los como assim dentro de minha classe Modelo abstrato:

abstract class Model_Abstract
{
    protected $_data;

    // Private Data Members assigned to protected $_data
    public function __construct($data = null)
    {
        // Makes it so that I can pass in an associative array as well as 
        // an StdObject.
        if(!is_object($data)) {
            $data = (object) $data;
        }

        $this->_data = $data;

    }

    public function __get($key)
    {
        if (method_exists($this, '_get' . ucfirst($key))) {
            $method = '_get' . ucfirst($key);
            return $this->$method();            
        }
        else {
            return $this->_data->$key;
        }   
    }

    public function __set($key, $val)
    {
        if ( method_exists( $this, '_set' . ucfirst($key) ) ) {
            $method = '_set' . ucfirst($key);
            return $this->$method($val);            
        }
        else {
            $this->_data->$key = $val;
            return $this->_data->$key;
        }
    }
}


class Model_User extends Model_Abstract
{
    //Example overriding method for the property firstName in the $_data collection.
    protected function _getFirstName()
    {
        // Do some special processing and then output the first name.
    }
}

Isso faz com que você pode especificar getters e setters para propriedades como necessário, mas faz com que você não tem que definir funções clichê para cada propriedade, apenas aqueles em que você quer fazer algum tipo de processamento sobre ele antes de retornar o valor. Por exemplo, eu usar a funcionalidade em um número de lugares de alterar as datas compatíveis com ISO (como armazenado no MySQL) em um formato mais compacto e legível para os usuários.

Tanto quanto o que colocar em seu controlador, eu recomendaria olhando para este post para algum feedback específico sobre o manuseio de lugar dentro de seu controlador.

Alguns acham que eles preferem ter um ajudante que carrega automaticamente modelos para a vista e saias o controlador completamente. Pessoalmente, eu diria que, no contexto do Zend Framework e PHP que faz muito sentido para passar modelos para a exibição do controlador porque o estado dos modelos na vista frequentemente depende do que veio do pedido (que deve definitivamente ser manuseado no controlador).

Update: Como por críticas nos comentários, uma coisa que eu gostaria de salientar é que a sua camada de acesso a banco de dados e domínio (ou modelo) camada são realmente duas coisas diferentes, embora com o Active Record eles são misturados em conjunto. Perguntei esta questão um back tempo e recebeu algum feedback útil Neste assunto. Tudo o que você decidir fazer com o modelo, você vai querer fornecer uma API consistente para todos os objetos de domínio, independentemente de onde os dados para o modelo vem.

Suponho que um benefício oferecido pela resposta de Saem é que ele oferece a capacidade de mapear diretamente propriedades / valores de retorno de função de um ou mais objetos de domínio em relação ao objeto de exibição. Teoricamente o uso dentro da visão, então fica assim:

// Mapped from Model_User::_data->last_name and Model_User::_data->first_name
$this->name 

Outras dicas

Se os outros desenvolvedores estão indo trabalhar com os modelos, eu recomendaria apenas passando nos modelos. Aqui está um link para um post Jeff Atwood sobre MVC Entendimento MVC

Este não é particularmente voltada para Zend Framework, mas o problema é bastante geral, em minha mente.

Parece que você está no caminho certo, em vez de fiação do modelo à vista, dentro do controlador. Você prefere ter esse resumo, especialmente importante se você está mapeando uma tonelada de modelos, ou mapear o mesmo modelo uma e outra vez.

Algo simples seria escrever um monte de funções de mapeamento, o que seria bom se tudo estivesse evitando é mapear a mesma coisa uma e outra.

Se você quiser uma solução mais geral, que também abordou escrita evitar que o código da placa de caldeira, e manter as coisas mais DRY, sugiro a criação de uma classe mapeador.

Você pode criar um ViewModelMapper, o que levaria um modelo, ou alguns modelos e mapeá-los para a vista.

class ViewModelMapper
{
    public function __construct($view)
    {
        //set the properties
    }

    public function addModel($model, $overrideViewProperty = null)
    {
        //add the model to the list of models to map, use the view's property 
        // name to figure out what to map it to? Allow for an override just in case.
    }

    public function getMappedView()
    {
        //take the view, map all the models
    }
}

Você pode então instância deste no seu controlador, e configurar os mapeamentos, para que os controles do controlador o mapeamento ainda, mas todos os placa de caldeira e da lógica de codificação é centralizado, para todos os mapas de controlador, com exceção das raras exceções.

Para uma boa leitura sobre a arquitetura do modelo, leia este post. Ele não falar especificamente sobre a visão, mas é definitivamente vale a pena a leitura.

acabei adicionando uma função getViewClass() aos meus modelos. O controlador chama essa função para obter as variáveis ??protegidas que não teriam acesso a, ea vista não tem que se preocupar em ligar para qualquer getters.

//controller
$object = new Object();
$object->setName('Foo Bar');
$this->view->object = $object->getViewClass();

//view template
<h2><?= $this->object->name ?></h2>

Eu não sei se existe uma maneira melhor de começar o trabalho feito no Zend Framework, mas esta é uma solução.

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