Понимание MVC-просмотров в PHP

Мне кажется, что проблемы, рассматривающие концепцию Views в MVC, они, в соответствии с тем, что я прочитал, являются слоем, который управляет представлением в приложении, но многие из материала, который я читал, по-видимому, отличаются от этого вопрос в этом от PHP Master.com .

View – это класс с функциями, возвращающими некоторый HTML-код, где находится остальная часть моего HTML-кода? следует ли его помещать в независимые .html-страницы, которые обращаются к этому коду просмотра?

В этой статье из php-html.net представление представляет собой простой HTML-файл с расширением .php, но как они обращаются к этим данным? Я не вижу require() или ничего подобного экземплярам в первом учебнике.

Примечание: шаблоны, созданные MVC и MVC, являются расширенными конструкциями. Они предназначены для использования в кодовых таблицах, где обычный объектно-ориентированный (который следует за SOLID и другими рекомендациями) код начинает становиться неуправляемым. Внедряя этот шаблон, вы наложите дополнительные ограничения, которые затем позволят вам содержать очень сложные приложения. MVC не предназначен для приложений «hello world».

Начнем с самого начала …

Основная идея шаблонов дизайна MVC и MVC – Разделение проблем . Указанное разделение является двукратным:

  • модельный слой отделен от слоя пользовательского интерфейса:
  • виды отделены от контроллеров

введите описание изображения здесь

Слой модели (не «класс» или «объект») будет содержать несколько групп структур, каждый из которых имеет дело с различным аспектом бизнес-логики. Основные части:

  • объекты домена : проверка, бизнес-правила
  • абстракция хранилища: сохранение и кэширование данных из доменных объектов
  • услуги: логика приложения

Также могут быть смешанные в хранилищах , единицах работы и других.

Уровень пользовательского интерфейса состоит в основном из представлений и контроллеров. Но они оба используют сервисы для взаимодействия с модельным слоем. Сервисы предоставляют возможность контроллерам изменять состояние уровня модели и представления для сбора информации на основе этого нового состояния.

В контексте сети представления и контроллеры образуют свободную пару из-за природы запроса-ответа, которую демонстрируют веб-приложения.

Следует отметить, что, хотя контроллеры могут напрямую изменять состояние текущего вида, чаще всего эти изменения производятся с помощью модели. Одной из причин непосредственного изменения вида является, например, когда вместо XML вы должны отвечать JSON.

Хотя также можно утверждать, что можно просто создать другое представление для каждого выходного формата и воспользоваться полиморфизмом.

Что не видно?

Существует распространенное заблуждение, что взгляды – это просто прославленный файл шаблона. Эта ошибка стала чрезвычайно популярной после выпуска растровой структуры RubyOnRails.

Представления не являются шаблонами . Если вы используете их как таковые, вы нарушаете основной принцип, лежащий в основе шаблонов MVC и MVC.

Если вы притворяетесь, что шаблоны являются видами, это оказывает огромное влияние на вашу архитектуру. В представлении нет места для логики представления, поэтому вы выдвигаете логику представления либо на уровне контроллера, либо на уровне модели. Обычный выбор – «контроллер», потому что большинство людей понимают, что логика представления не имеет места в слое модели.

По сути, это вызывает слияние взглядов и контроллеров.

Что такое просмотр?

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

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

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

При использовании Post / Redirect / Get часть перенаправления выполняется представлением, а не контроллером, как часто люди склонны делать.


Очень субъективный бит :

В последнее время я предпочел взаимодействовать с MVC, используя следующий подход:

  // the factory for services was injected in constructors $controller->{ $method.$command }($request); $view->{ $command }(); $view->respond(); 

Метод $method – текущий REQUEST_METHOD , который был скорректирован с помощью REST-подобного API, а команда $command – это то, что люди обычно называют «действием». Контроллер имеет отдельные подпрограммы для запросов GET и POST (другого). Это помогает избежать того же, if в каждом «действии».

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

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

Как насчет СУХОЙ?

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

Давайте посмотрим на разбивку на страницы. В папке есть логика, но эта логика не связана с модельным слоем. Модель не имеет понятия «страница». Вместо этого этот бит логики будет находиться в слое пользовательского интерфейса. Но если каждое из ваших представлений содержит или наследует разбивку на страницы, то это будет явным нарушением SRP (и фактически нескольких других принципов тоже).

Чтобы избежать этой проблемы, вы можете (и должны, IMHO) вводить объекты презентации в свои представления.

Примечание: в то время как Фаулер называет их «презентационными моделями», я думаю, что это имя просто добавляет к путанице целого «что такое модель». Поэтому я бы рекомендовал вместо них назвать «объекты презентации».

Объекты презентации имеют дело с повторяющимися фрагментами логики. Это делает взгляды «более легкими» , и в некоторых аспектах начинает отражать структуру услуг с уровня модели.

Взаимодействие между объектами представления и шаблонами становится похожим на взаимодействие между объектами домена и данными .

Всегда ли мне нужно все это?

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

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

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


PS Я сам все еще борется с тем, как лучше всего разобраться с мнениями. Это сообщение меньше ответа и больше похоже на снимок моего нынешнего понимания.

Второй учебник – это то, как работает среда Code Igniter, и тот, к которому я привык. Я слежу за ним, даже если вообще не использую рамки.

На самом деле разработчик должен на практике применять MVC-подобные принципы, иначе он может сделать лазаньи или спагетти даже с использованием большинства ориентированных на MVC рамок.

Используя подход «PHP-файл как шаблон представления», в идеале можно использовать минимальные инструкции PHP, в основном только для повторных структур ( foreach ($array as $item) ), базовых условных выражений ( if ($boolean) ) и echo – как бы это был, действительно, шаблонный язык, и ничего более.

Таким образом, теги <?php ?> файлах шаблона представления должны быть просто заполнителями , и ничего больше.

Никакие запросы к базе данных, доступ к модели, вычисления и т. П. Не должны выполняться в файле шаблона представления. Его следует рассматривать, в основном, как файл HTML с заполнителями. (С его связанными CSS и JavaScript. Все может усложниться, когда приложение опирается на JavaScript / AJAX много …)

Следуя этим простым принципам, мы фактически делаем некоторое разделение презентации от бизнес-логики. Даже звучание настолько простое, что мне надоело иметь код Code Igniter, который не следует за ним. Некоторые используют «вспомогательные функции» для маскировки вызовов модели / базы данных и считают, что это хорошая практика! 🙂

Вы не видите require в этих файлах шаблонов PHP-файлов, потому что они необходимы вместо этого из методов «view building».

Конечно, не следует echo и / или print изнутри контроллера и функций модели. Это тоже очень просто, но я также устал видеть, что код спагетти перекликается с HTML из методов контроллера CI.

На практике контроллер вызывает методы модели, создает все необходимые данные для представления и в качестве последнего шага вызывает представление (т. Е. Строит и выводит его), передавая ему ранее полученные данные.

Имеет смысл? Я не знаю, ответил ли я на ваш вопрос. По крайней мере, это мои «2 цента».

В разных структурах используется другая логика для назначения переменных для просмотра и получения содержимого. Ниже приведен простой пример с использованием функции ob_start ().

 <?php $title = 'Hello...'; ob_start(); file_get_contents('view.phtml'); $viewContents = ob_get_clean(); echo $viewContents; ?> //view.phtml <b>Hello the title is <?php echo $title; ?></b> 

Надеюсь, что ответ на ваш вопрос …

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

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

Изменить: каждый модуль, представленный набором MVC, будет иметь свой собственный вид, который содержит набор методов, ответственных за отправку вашего вывода в браузер. Есть много способов, которыми вы можете пойти, но вот один пример:

 class testModule_view extends viewAbstract { public function showTestData($title, $subtitle, $data) { $XHTML = '<h1>' . $title . '</h1>' . '<h2>' . $subtitle . '</h2>' . parent::data2table($data); parent::outputToBrowser(DEFAULT_TEMPLATE, $XHTML); } } 

Это просто быстрый пример, чтобы дать вам представление о том, как выглядит простой метод просмотра.

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

 <?php 

class View {

 protected $data; protected $path; protected static function getDefaultViewPath() { $router = App::getRouter(); if(!$router){ return false; } $controller_path = $router->getController(); $method_path = ($router->getMethodPrefix() !== "" ? $router->getMethodPrefix() . '_' : '') . $router->getAction(); return ROOT . "/views/" . $controller_path . "/" . $method_path . ".phtml"; } public function __construct($data = array(), $path = null) { if(!$path){ //default $path = $this->getDefaultViewPath(); } if(!file_exists($path)){ throw new Exception("Error view file!"); } $this->data = $data; $this->path = $path; } public function render(){ $data = $this->data; ob_start(); include ($this->path); $content = ob_get_clean(); return $content; } 

}

Проверьте этот код:

 include_once(ROOT.'/'.'config/config.php'); function __autoload($class_name){ $lib_path = ROOT . '/' . 'lib/class.'.$class_name . '.php'; $controller_path = ROOT . '/' . 'controllers/'.str_replace("controller", "", strtolower($class_name)) . '.controller.php'; $model_path = ROOT . '/' . 'models/'.strtolower($class_name) . '.php'; if(file_exists($lib_path)){ require_once ($lib_path); } else if (file_exists($controller_path)){ require_once ($controller_path); } else if(file_exists($model_path)){ require_once ($model_path); } else { throw new Exception("File {$class_name} cannot be found!"); } }