Фреймворк Zend:Использование моделей и представлений, лучшие практики [закрыто]

StackOverflow https://stackoverflow.com/questions/603935

  •  03-07-2019
  •  | 
  •  

Вопрос

Я относительно новичок в объектно-ориентированном программировании.Я в значительной степени разбираюсь в концепциях, но, с практической точки зрения, мне действительно трудно найти информацию о том, как наилучшим образом использовать модели в моих приложениях 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?Кто-нибудь может порекомендовать какой-либо учебник, который помог бы мне понять эту дилемму модели / представления в Zend Framework?

Это было полезно?

Решение

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

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), в более компактный и удобочитаемый формат для пользователей.

Что касается того, что разместить в вашем контроллере, я бы рекомендовал посмотреть на этот пост для получения некоторых конкретных отзывов о том, какую обработку следует разместить в вашем контроллере.

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

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

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

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

Другие советы

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

Это не особенно ориентировано на zend framework, но, на мой взгляд, проблема довольно общая.

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

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

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

Вы могли бы создать 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
    }
}

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

Для получения дополнительной информации об архитектуре модели, прочтите этот пост.В нем конкретно не говорится о виде, но его определенно стоит прочитать.

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

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

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top