2009-03-02 2 views
9

Я относительно новичок в объектно-ориентированном программировании. Я в значительной степени понимаю понятия, но, на самом деле, мне очень сложно найти информацию о том, как наилучшим образом использовать модели в своих приложениях Zend Framework.Zend Framework: использование моделей и представлений, лучшие практики

В частности, у меня есть модель (которая не распространяется ни на что), которая не использует таблицу базы данных. Он использует геттеры и сеттеры для доступа к своим защищенным членам. Я считаю, что борюсь с тем, как лучше всего отображать эту модель в представлении. Я не хочу логики в моих шаблонах, но я считаю себя в следующей ситуации:

В моем контроллере:

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

В моем шаблоне вида:

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

Я не» Мне очень нравятся функции вызова в моих шаблонах, но я не знаю, как это сделать. Я не хочу, члены моей модели, чтобы быть открытыми, но я в принципе хочу, чтобы достичь тех же результатов:

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

Я не хочу, чтобы мой контроллер сделать всю работу того, чтобы знать все о модели:

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

Какова наилучшая практика использования моделей в Zend Framework? Может ли кто-нибудь порекомендовать какой-либо учебник, который поможет мне понять эту дилемму Model/View в Zend Framework?

ответ

4

Одной из возможностей является использование магических методов __set и __get в PHP.Я использую их, как это в моем абстрактном классе Model:

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

Это делает его так, что вы можете указать методы получения и установки для свойств, необходимых, но делает это так, что вы не должны определять функции стереотипных для каждого свойства , только те, где вы хотите сделать некоторую обработку на нем, прежде чем возвращать значение. Например, я использую функциональность в ряде мест, чтобы изменить даты, соответствующие ISO (как хранятся в MySQL), в более компактный и читаемый формат для пользователей.

Что касается места в вашем контроллере, я бы рекомендовал посмотреть на this post для получения конкретной информации о том, какая обработка должна размещаться внутри вашего контроллера.

Некоторые считают, что у них скорее будет помощник, который автоматически загружает модели в представление и полностью обходит контроллер. Лично я бы сказал, что в контексте Zend Framework и PHP имеет смысл передавать модели в представление с контроллера, потому что состояние моделей в представлении часто зависит от того, что исходило от запроса (что определенно должно быть обработано в контроллере).

Обновление: В соответствии с критикой в ​​комментариях, одна вещь, на которую я хотел бы обратить внимание, заключается в том, что уровень доступа к базе данных и уровень домена (или модели) - это действительно две разные вещи, хотя с Активной записью они смешиваются вместе , Я спросил this question некоторое время назад и получил некоторые полезные отзывы по этому вопросу. Независимо от того, что вы решили сделать с моделью, вы захотите предоставить согласованный API для всех объектов домена независимо от того, откуда берутся данные для модели.

Я полагаю, что одно преимущество, предлагаемое ответом Сайма, заключается в том, что оно дает возможность напрямую отображать значения свойств/функций из одного или нескольких объектов домена в объект вида. Теоретически использование в представлении будет выглядеть следующим образом:

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

Это на самом деле плохой способ делать что-то. Вы не только произвольно получаете доступ ко всем свойствам, независимо от того, являются ли они теми, которые должны быть (un) сериализованы в/из формы или нет, а также перегружают модель концепцией сопоставления, что и требовалось. – Saem

+0

Ввод логики формы в модель смешивает представление и модель, которая также является плохой формой. И, как я уже сказал, переопределение поведения по умолчанию очень простое и позволяет избежать необходимости создания глупых шаблонных геттеров и сеттеров. –

+0

И если вы посмотрите на класс Zend_Db_Table_Row, вы обнаружите, что Zend фактически использует аналогичный принцип, чтобы выставлять поля и их значения из таблиц. –

3

Если только другие разработчики будут работать с шаблонами, я бы рекомендовал просто пропустить в моделях. Вот ссылка на пост Джеффа Этвуда на MVC Understanding Model-View-Controller

3

Это не особенно ориентировано на zend-фреймворк, но проблема в моем понимании довольно распространена.

Кажется, вы на правильном пути, вместо жесткой проводки модели к виду внутри контроллера. Вы бы предпочли бы этот абстрактный, особенно важный, если бы вы отображали тонны моделей или отображали одну и ту же модель снова и снова.

Что-то простое было бы написать кучу функций отображения, что было бы прекрасно, если бы все, что вы избегали, - это повторять одно и то же снова и снова.

Если вы хотите получить более общее решение, которое также должно было бы избежать написания кода плиты котла и хранения вещей более СУХОЙ, я предлагаю создать класс сопоставления.

Вы можете создать ViewModelMapper, который возьмет модель или несколько моделей и отобразит их в представлении.

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

Вы могли бы затем экземпляр этого на контроллере, и настройка отображения, так что контроллер управляет отображением еще, но все плиты котла и логика кодирования централизовано для всех карт контроллера, за редким исключением, за исключением ,

+0

Просьба привести соответствующий пример, в котором используется этот класс Mapper. На данный момент все, что я вижу, это способ сделать Моделирование более сложным. –

1

Для хорошего чтения на модели архитектуры, read this post. В нем конкретно не говорится о представлении, но это определенно стоит прочитать.

В итоге я добавила функцию getViewClass() к моим моделям. Контроллер вызывает эту функцию, чтобы получить защищенные переменные, к которым у нее иначе не было бы доступа, и представление не должно беспокоиться о вызове каких-либо геттеров.

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

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

Я не знаю, если есть лучший способ, чтобы получить работу в Zend Framework, но это одно решение.