Вы можеть быть даже слышали о шаблонах проектирования и даже листали эти прекрасные книги:
Представленная статья будет полезна в первую очередь новичкам. Во всяком случае, я надеюсь что за пару часов вы сможете получить представление о реализации MVC паттерна, который лежит в основе всех современных веб-фреймворков, а также получить «пищу» для дальнейших размышлений над тем - «как стоит делать». В конце статьи приводится подборка полезных ссылок, которые также помогут разобраться из чего состоят веб-фреймворки (помимо MVC) и как они работают.
Прожженные PHP-программисты вряд ли найдут в данной статье что-то новое для себя, но их замечания и комментарии к основному тексту были бы очень кстати! Т.к. без теории практика невозможна, а без практики теория бесполезна, то сначала будет чуть-чуть теории, а потом перейдем к практике. Если вы уже знакомы с концепцией MVC, можете пропустить раздел с теорией и сразу перейти к практике.
1. Теория Шаблон MVC описывает простой способ построения структуры приложения, целью которого является отделение бизнес-логики от пользовательского интерфейса. В результате, приложение легче масштабируется, тестируется, сопровождается и конечно же реализуется.Рассмотрим концептуальную схему шаблона MVC (на мой взгляд - это наиболее удачная схема из тех, что я видел):
В архитектуре MVC модель предоставляет данные и правила бизнес-логики, представление отвечает за пользовательский интерфейс, а контроллер обеспечивает взаимодействие между моделью и представлением.
Типичную последовательность работы MVC-приложения можно описать следующим образом:
Вид
- используется для задания внешнего отображения данных, полученных из контроллера и модели.
Виды cодержат HTML-разметку и небольшие вставки PHP-кода для обхода, форматирования и отображения данных.
Не должны напрямую обращаться к базе данных. Этим должны заниматься модели.
Не должны работать с данными, полученными из запроса пользователя. Эту задачу должен выполнять контроллер.
Может напрямую обращаться к свойствам и методам контроллера или моделей, для получения готовых к выводу данных.
Виды обычно разделяют на общий шаблон, содержащий разметку, общую для всех страниц (например, шапку и подвал) и части шаблона, которые используют для отображения данных выводимых из модели или отображения форм ввода данных.
Контроллер
- связующее звено, соединяющее модели, виды и другие компоненты в рабочее приложение. Контроллер отвечает за обработку запросов пользователя. Контроллер не должен содержать SQL-запросов. Их лучше держать в моделях. Контроллер не должен содержать HTML и другой разметки. Её стоит выносить в виды.
В хорошо спроектированном MVC-приложении контроллеры обычно очень тонкие и содержат только несколько десятков строк кода. Чего, не скажешь о Stupid Fat Controllers (SFC) в CMS Joomla. Логика контроллера довольно типична и большая ее часть выносится в базовые классы.
Модели, наоборот, очень толстые и содержат большую часть кода, связанную с обработкой данных, т.к. структура данных и бизнес-логика, содержащаяся в них, обычно довольно специфична для конкретного приложения.
Надеюсь, вы уже успели заметить, что у разных сайтов могут быть совершенные разные форматы построения адресной строки. Каждый формат может отображать архитектуру web-приложения. Хотя это и не всегда так, но в большинстве случаев это явный факт.
Рассмотрим два варианта адресной строки, по которым показывается какой-то текст и профиль пользователя.
Приблизительный код обработки в таком случае:
switch($_GET["action"])
{
case "about" :
require_once("about.php"); // страница "О Нас"
break;
case "contacts" :
require_once("contacts.php"); // страница "Контакты"
break;
case "feedback" :
require_once("feedback.php"); // страница "Обратная связь"
break;
default:
require_once("page404.php"); // страница "404"
break;
}
Думаю, почти все так раньше делали.
С использованием движка маршрутизации URL вы сможете для отображения той же информации настроить приложение на прием таких запросов:
http://www.example.com/contacts/feedback
Здесь contacts представляет собой контроллер, а feedback - это метод контроллера contacts, отображающий форму обратной связи и т.д. Мы еще вернемся к этому вопросу в практической части.
Также стоит знать, что маршрутизаторы многих веб-фреймворков позволяют создавать произвольные маршруты URL (указать, что означает каждая часть URL) и правила их обработки.
Теперь мы обладаем достаточными теоретическими знаниями, чтобы перейти к практике.
Забегая вперед, скажу, что в папке core будут храниться базовые классы Model, View и Controller.
Их потомки будут храниться в директориях controllers, models и views. Файл index.php
это точка в хода в приложение. Файл bootstrap.php
инициирует загрузку приложения, подключая все необходимые модули и пр.
Будем идти последовательно; откроем файл index.php и наполним его следующим кодом:
ini_set("display_errors", 1);
require_once "application/bootstrap.php";
Тут вопросов возникнуть не должно.
Следом, сразу же перейдем к фалу bootstrap.php
:
require_once "core/model.php";
require_once "core/view.php";
require_once "core/controller.php";
require_once "core/route.php";
Route::start(); // запускаем маршрутизатор
Первые три строки будут подключать пока что несуществующие файлы ядра. Последние строки подключают файл с классом маршрутизатора и запускают его на выполнение вызовом статического метода start.
Маршрутизацию мы поместим в отдельный файл route.php в директорию core. В этом файле опишем класс Route, который будет запускать методы контроллеров, которые в свою очередь будут генерировать вид страниц.
Содержимое файла route.php
class Route
{
static function start()
{
// контроллер и действие по умолчанию
$controller_name = "Main";
$action_name = "index";
$routes = explode("/", $_SERVER["REQUEST_URI"]);
// получаем имя контроллера
if (!empty($routes))
{
$controller_name = $routes;
}
// получаем имя экшена
if (!empty($routes))
{
$action_name = $routes;
}
// добавляем префиксы
$model_name = "Model_".$controller_name;
$controller_name = "Controller_".$controller_name;
$action_name = "action_".$action_name;
// подцепляем файл с классом модели (файла модели может и не быть)
$model_file = strtolower($model_name).".php";
$model_path = "application/models/".$model_file;
if(file_exists($model_path))
{
include "application/models/".$model_file;
}
// подцепляем файл с классом контроллера
$controller_file = strtolower($controller_name).".php";
$controller_path = "application/controllers/".$controller_file;
if(file_exists($controller_path))
{
include "application/controllers/".$controller_file;
}
else
{
/*
правильно было бы кинуть здесь исключение,
но для упрощения сразу сделаем редирект на страницу 404
*/
Route::ErrorPage404();
}
// создаем контроллер
$controller = new $controller_name;
$action = $action_name;
if(method_exists($controller, $action))
{
// вызываем действие контроллера
$controller->$action();
}
else
{
// здесь также разумнее было бы кинуть исключение
Route::ErrorPage404();
}
}
function ErrorPage404()
{
$host = "http://".$_SERVER["HTTP_HOST"]."/";
header("HTTP/1.1 404 Not Found");
header("Status: 404 Not Found");
header("Location:".$host."404");
}
}
В элементе глобального массива $_SERVER["REQUEST_URI"] содержится полный адрес по которому обратился пользователь.
Например: example.ru/contacts/feedback
С помощью функции explode производится разделение адреса на составлющие. В результате мы получаем имя контроллера, для приведенного примера, это контроллер contacts и имя действия, в нашем случае - feedback .
Далее подключается файл модели (модель может отсутствовать) и файл контроллера, если таковые имеются и наконец, создается экземпляр контроллера и вызывается действие, опять же, если оно было описано в классе контроллера.
Таким образом, при переходе, к примеру, по адресу:
example.com/portfolio
или
example.com/portfolio/index
роутер выполнит следующие действия:
Напомню, что они будут содержать базовые классы, к написанию которых мы сейчас и приступим.
Содержимое файла model.php
class Model
{
public function get_data()
{
}
}
Класс модели содержит единственный пустой метод выборки данных, который будет перекрываться в классах потомках. Когда мы будем создавать классы потомки все станет понятней.
Содержимое файла view.php
class View
{
//public $template_view; // здесь можно указать общий вид по умолчанию.
function generate($content_view, $template_view, $data = null)
{
/*
if(is_array($data)) {
// преобразуем элементы массива в переменные
extract($data);
}
*/
include "application/views/".$template_view;
}
}
Не трудно догадаться, что метод generate
предназначен для формирования вида. В него передаются следующие параметры:
В нашем случае общий шаблон будет содержать header, menu, sidebar и footer, а контент страниц будет содержаться в отдельном виде. Опять же это сделано для упрощения.
Содержимое файла controller.php
class Controller {
public $model;
public $view;
function __construct()
{
$this->view = new View();
}
function action_index()
{
}
}
Метод action_index
- это действие, вызываемое по умолчанию, его мы перекроем при реализации классов потомков.
На предыдущем рисунке отдельно выделен файл template_view.php
- это шаблон, содержащий общую для всех страниц разметку. В простейшем случае он мог бы выглядеть так:
Главная
Для придания сайту презентабельного вида сверстаем CSS шаблон и интегририруем его в наш сайт путем изменения структуры HTML-разметки и подключения CSS и JavaScript файлов:
В конце статьи, в разделе «Результат», приводится ссылка на GitHub-репозиторий с проектом, в котором проделаны действия по интеграции простенького шаблона.
Файл с общим видом мы рассмотрели ранее. Рассмотрим файл контента main_view.php
:
Добро пожаловать!
ОЛОЛОША TEAM - команда первоклассных специалистов в области разработки веб-сайтов с многолетним опытом коллекционирования мексиканских масок, бронзовых и каменных статуй из Индии и Цейлона, барельефов и изваяний, созданных мастерами Экваториальной Африки пять-шесть веков назад...
Класс контроллера модели содержится в файле controller_portfolio.php
, вот его код:
class Controller_Portfolio extends Controller
{
function __construct()
{
$this->model = new Model_Portfolio();
$this->view = new View();
}
function action_index()
{
$data = $this->model->get_data();
$this->view->generate("portfolio_view.php", "template_view.php", $data);
}
}
В переменную data
записывается массив, возвращаемый методом get_data
, который мы рассматривали ранее.
Далее эта переменная передается в качестве параметра метода generate
, в который также передаются: имя файла с общим шаблон и имя файла, содержащего вид c контентом страницы.
Вид содержащий контент страницы находится в файле portfolio_view.php
.
Портфолио
Год | Проект | Описание |
Скриншот получившегося сайта-визитки
А вот в этой версии я набросал следующие классы (и соответствующие им виды):
Но, использование веб-фреймворков, типа Yii или Kohana, состоящих из нескольких сотен файлов, при разработке простых веб-приложений (например, сайтов-визиткок) не всегда целесообразно. Теперь мы умеем создавать красивую MVC модель, чтобы не перемешивать Php, Html, CSS и JavaScript код в одном файле.
Данная статья является скорее отправной точкой для изучения CMF, чем примером чего-то истинно правильного, что можно взять за основу своего веб-приложения. Возможно она даже вдохновила Вас и вы уже подумываете написать свой микрофреймворк или CMS, основанные на MVC. Но, прежде чем изобретать очередной велосипед с «блекджеком и шлюхами», еще раз подумайте, может ваши усилия разумнее направить на развитие и в помощь сообществу уже существующего проекта?!
P.S.: Статья была переписана с учетом некоторых замечаний, оставленных в комментариях. Критика оказалась очень полезной. Судя по отклику: комментариям, обращениям в личку и количеству юзеров добавивших пост в избранное затея написать этот пост оказалось не такой уж плохой. К сожалению, не возможно учесть все пожелания и написать больше и подробнее по причине нехватки времени… но возможно это сделают те таинственные личности, кто минусовал первоначальный вариант. Удачи в проектах!
5. Подборка полезных ссылок по сабжу В статье очень часто затрагивается тема веб-фреймворков - это очень обширная тема, потому что даже микрофреймворки состоят из многих компонентов хитро увязанных между собой и потребовалась бы не одна статья, чтобы рассказать об этих компонентах. Тем не менее, я решил привести здесь небольшую подборку ссылок (по которым я ходил при написаниие этой статьи), которые так или иначе касаются темы фреймворков.Теги: Добавить метки
Model-View-Controller (MVC , «Модель-Представление-Контроллер», «Модель-Вид-Контроллер») - схема разделения данных приложения, пользовательского интерфейса и управляющей логики на три отдельных компонента: модель, представление и контроллер - таким образом, что модификация каждого компонента может осуществляться независимо .
Энциклопедичный YouTube1 / 5
Концепция MVC была описана Трюгве Реенскаугом в 1978 году , работавшем в научно-исследовательском центре «Xerox PARC » над языком программирования «Smalltalk ». Позже, Стив Бурбек реализовал шаблон в Smalltalk-80 .
Впоследствии, шаблон проектирования стал эволюционировать. Например, была представлена иерархическая версия HMVC ; MVA, MVVM .
После внедрения компанией Apple технологии WebObjects, реализованных на Objective-C, стало популяризировать шаблон и в вебе [ ] .
Когда WebObjects портировали на Java, шаблон стал популярен и там. Более поздние фреймворки вроде Spring (октябрь 2002 года) всё ещё имеют реализацию MVC [ ] .
Дальнейший виток популярности привнесло развитие фреймворков, ориентированных на быструю развёртку, на языках Python и Ruby, Django и Rails, соответственно [ ] . На момент 2017 года, фреймворки с MVC заняли заметные позиции по отношению к остальным фреймворкам без этого шаблона .
Различия описания концепции шаблонаС развитием объектно-ориентированного программирования и понятия о шаблонах проектирования - был создан ряд модификаций концепции MVC, которые при реализации у разных авторов могут отличаться от оригинальной. Так, например, Эриан Верми в 2004 году описал пример обобщённого MVC .
В предисловии к диссертации «Naked objects » Ричарда Поусона (Richard Pawson), - Трюгве Реенскауг упоминает свою неопубликованную наиболее раннюю версию MVC, согласно которой :
Основная цель применения этой концепции состоит в отделении бизнес-логики (модели ) от её визуализации (представления , вида ). За счёт такого разделения повышается возможность повторного использования кода . Наиболее полезно применение данной концепции в тех случаях, когда пользователь должен видеть те же самые данные одновременно в различных контекстах и/или с различных точек зрения. В частности, выполняются следующие задачи:
Концепция MVC позволяет разделить модель, представление и контроллер на три отдельных компонента:
МодельМодель предоставляет данные и методы работы с ними: запросы в базу данных, проверка на корректность. Модель не зависит от представления - не знает как данные визуализировать - и контроллера - не имеет точек взаимодействия с пользователем -, просто предоставляя доступ к данным и управлению ими.
Модель строится таким образом, чтобы отвечать на запросы, изменяя своё состояние, при этом может быть встроено уведомление «наблюдателей».
Модель, за счёт независимости от визуального представления, может иметь несколько различных представлений для одной «модели».
ПредставлениеПредставление отвечает за получение необходимых данных из модели и отправляет их пользователю. Представление не обрабатывает введённые данные пользователя [ ] .
Представление может влиять на состояние модели сообщая модели об этом.
КонтроллерКонтроллер обеспечивает «связи» между пользователем и системой. Контролирует и направляет данные от пользователя к системе и наоборот. Использует модель и представление для реализации необходимого действия.
Функциональные возможности и расхожденияПоскольку MVC не имеет строгой реализации, то реализован он может быть по-разному. Нет общепринятого определения, где должна располагаться бизнес-логика. Она может находиться как в контроллере, так и в модели. В последнем случае, модель будет содержать все бизнес-объекты со всеми данными и функциями.
Некоторые фреймворки жестко задают где должна располагаться бизнес-логика, другие не имеют таких правил.
Также не указано, где должна находиться проверка введённых пользователем данных. Простая валидация может встречаться даже в представлении, но чаще они встречаются в контроллере или модели.
Интернационализация и форматирование данных также не имеет четких указаний по расположению.
Условно-обязательные модификацииДля реализации схемы «Model-View-Controller» используется достаточно большое число шаблонов проектирования (в зависимости от сложности архитектурного решения), основные из которых - «наблюдатель », «стратегия », «компоновщик » :
Наиболее типичная реализация - в которой вид отделён от модели путём установления между ними протокола взаимодействия, использующего «аппарат событий» (обозначение «событиями» определённых ситуаций, возникающих в ходе выполнения программы, - и рассылка уведомлений о них всем тем, кто подписался на получение): при каждом особом изменении внутренних данных в модели (обозначенном как «событие»), она оповещает о нём те зависящие от неё представления, которые подписаны на получение такого оповещения - и представление обновляется. Так используется шаблон «наблюдатель »;
При обработке реакции пользователя - представление выбирает, в зависимости от реакции, нужный контроллер , который обеспечит ту или иную связь с моделью. Для этого используется шаблон «стратегия », или вместо этого может быть модификация с использованием шаблона «команда »;
Для возможности однотипного обращения с подобъектами сложно-составного иерархического вида - может использоваться шаблон «компоновщик ». Кроме того, могут использоваться и другие шаблоны проектирования - например, «фабричный метод », который позволит задать по умолчанию тип контроллера для соответствующего вида.
Наиболее частые ошибкиНачинающие программисты очень часто трактуют архитектурную модель MVC как пассивную модель MVC: модель выступает исключительно совокупностью функций для доступа к данным, а контроллер содержит бизнес-логику . В результате - код моделей по факту является средством получения данных из СУБД , а контроллер - типичным модулем , наполненным бизнес-логикой (см. «скрипт » в терминологии веб-программирования). В результате такого понимания - MVC-разработчики стали писать код, который Pádraic Brady (известный в кругах сообщества «Zend Framework ») охарактеризовал как «ТТУК» («Толстые, тупые, уродливые контроллеры»; Fat Stupid Ugly Controllers):
Среднестатистический ТТУК получал данные из БД (используя уровень абстракции базы данных, делая вид, что это модель) или манипулировал, проверял, записывал, а также передавал данные в Представление. Такой подход стал очень популярен потому, что использование таких контроллеров похоже на классическую практику использования отдельного php-файла для каждой страницы приложения.
Но в объектно-ориентированном программировании используется активная модель MVC, где модель - это не только совокупность кода доступа к данным и
Фреймворк Bootstrap: быстрая адаптивная вёрстка
Пошаговый видеокурс по основам адаптивной верстки в фреймворке Bootstrap.
Научитесь верстать просто, быстро и качественно, используя мощный и практичный инструмент.
Верстайте на заказ и получайте деньги.
Бесплатный курс "Сайт на WordPress"
Хотите освоить CMS WordPress?
Получите уроки по дизайну и верстке сайта на WordPress.
Научитесь работать с темами и нарезать макет.
Бесплатный видеокурс по рисованию дизайна сайта, его верстке и установке на CMS WordPress!
*Наведите курсор мыши для приостановки прокрутки.
Назад Вперед
Удобный подход к веб-разработке: Модель MVCЧто такое MVC? Если отвечать кратко, то это подход к разработке, позволяющий добиться более структурированного кода и приложения в целом.
Расшифровывается MVC как "Модель-Вид-Контроллер" (Model-View-Controller). Давайте поговорим об этом подробнее.
На сегодняшний день можно выделить два наиболее типичных способа создания веб-приложений (сайтов).
Первый способ , назовем его "Классическим", предполагает то, что в одном файле может содержаться код различных языков программирования и разметки.
Скажем, в начале файла производится запрос к базе данных для получения из нее какой-либо информации. Здесь мы имеем дело с языком SQL - специальным языком запросов, предназначенным для взаимодействия с базой данных.
После этого, как правило, начинается html-разметка страницы (куда же без нее?). Причем внутри html-разметки в нужных местах производятся вставки PHP-кода, которые производят управление сайтом, являются его логикой. Итого мы имеем в одном файле: SQL, (X)HTML и PHP. Это уже - сборная солянка. Не забудьте добавить сюда еще CSS и немного Javascript для полноты картины, и, в итоге мы получим такую кашу, что в этом файле сам черт ногу сломит.
Конечно, первое время вы будете помнить, что и как у вас в нем происходит, зачем что нужно, и где нужно вносить изменения для добавления / удаления / модификации определенного функционала. Однако я гарантирую вам, что уже через несколько месяцев вы будете смотреть на свой код с недоумением, силясь вспомнить, что же с чем связано, какие изменения "потянутся" после изменения какого-либо файла и т.п.
Я не говорю, что нужно полностью отказываться от такого подхода, однако ясно, что пользоваться им надо с умом и очень осторожно.
Второй способ связан как раз-таки с применением схемы "Модель-Вид-Контроллер" .
В чем суть данного подхода, и как его использование может помочь вам в работе?
Основная идея данного подхода заключается в необходимости разделения однородных элементов по разным файлам . Если говорить очень упрощенно: один файл - один язык. Но это очень грубый пример. Такое встречается крайне редко.
Помимо идеи разнесения разных языков в разные файлы, ключевой концепцией является также разделение файлов на группы в соответствии с теми функциями, которые они выполняют в приложении .
Здесь мы начинаем с вами подходить к более подробному рассмотрению модели MVC.
Данная модель подразумевает разделение всех файлов, задействованных при разработке сайта на три группы:
1. Файлы группы "модель"
2. Файлы группы "контроллер"
3. Файлы группы "вид"
Здесь важно сразу понять, что название схемы MVC - условность. В вашем приложении, естественно, может быть много моделей, контроллеров и видов (т.е. файлов, попадающих под эти группы по выполняемым ими функциям и внутреннему устройству).
Итак, давайте посмотрим на сравнительную схему модели MVC и "классического" способа разработки .
В левой части вы видите как раз то, о чем мы говорили выше. Вверху страницы - SQL-запросы к базе. Затем разметка плюс вставки PHP.
Справа же приведена простейшая схема модели MVC. В рамках данной схемы в модели происходят операции, связанные с взаимодействием с базой данных : извлечение данных, их модификация и удаление, подсчет количества записей в определенных таблицах и т.п.
В контроллере находится логика приложения , т.е. то, что определяет его функционал.
Вид же предназначен для показа конечному пользователю .
Двунаправленные стрелки на схеме показывают то, что в парах "Модель - Контроллер" и "Контроллер - Вид" существует взаимосвязь. Рассмотрим эту взаимосвязь подробнее на примере следующей схемы.
На этой схеме у нас добавилось два новых элемента: браузер пользователя и база данных. Рассмотрим в общих чертах весь цикл: от обращения браузера к определенному url-адресу до момента отображения страницы для пользователя:
1. Пользователь вводит адрес, и браузер обращается к контроллеру.
2. Контроллер обращается к модели.
3. Модель обращается к базе данных (к примеру, для получения необходимой для вывода информации)
4. Информация из базы попадает обратно в модель.
5. Из модели информация передается в контроллер.
6. Контроллер передает эту информацию в вид.
7. Вид выводится в браузер с помощью контроллера.
Такова общая схема работы данной модели. Как вы можете видеть, некоторым особняком на данной схеме стоят браузер и база данных. Действительно, браузер может обращаться только к контроллеру, так как контроллер является частью url-адреса . Посетитель не может обратиться к чему бы то ни было, кроме контроллера. Это важно понимать. Человек не может через адресную строку обращаться к видам или моделям. Он взаимодействует только с контроллером.
В связи с этим можно говорить о контроллере как о своеобразном "распределительном центре". Смотрите сами: контроллер обрабатывает запросы пользователя, контроллер обращается к модели, контроллер же является посредником для вывода вида в браузер.
Второй элемент, стоящий особняком - база данных. И это правильно. В рамках концепции MVC принято, что с базой должны работать только модели , однако иногда этот принцип нарушается. При этом взаимодействие с базой производится из контроллера или даже вида.
Разумеется, не стоит перегибать палку с нарушением структуры и принципов MVC, но иногда такой отход от правил может быть очень полезен с точки зрения улучшения читаемости кода и понимания схемы работы приложения.
Модель , кстати сказать, является необязательным элементом в схеме MVC . Вполне можно реализовать все, что нужно, не используя моделей в принципе. Естественно, в этом случае вы будете взаимодействовать с базой данных из файлов контроллера и вида. Как вы уже поняли, это не очень хороший тон. Коль скоро вы решили работать в рамках данной концепции, рекомендуется использовать модели и делать это по их прямому назначению.
"Крайних" мы рассмотрели, а в центре схемы так и осталась наша троица, где происходят взаимодействия "Модель - Контроллер" и "Контроллер - Вид".
После того, как мы изучили основы работы данной модели, можно задуматься над тем, что дает нам такой подход, чем он предпочтительнее классического.
Основная выгода от применения такой схемы в своей работе уже была упомянута - это повышение структурированности кода и приложения в целом . Не секрет, что модель MVC взята на вооружение многим производителями фреймворков, среди которых есть и любимый мной CodeIgniter.
Ведь что из себя представляет фреймворк? Если отбросить иностранное слово, то это просто каркас, определенная структура, по которой вам предлагается разрабатывать сайт. Данная структура является достаточно универсальной, чтобы создать с ее помощью практически любой сайт. При этом, что очень важно, фреймворк одновременно является и очень гибким, позволяя добиваться именно того, что вам нужно.
Говоря другим языком, фреймоворк - это гибкие рамки, которые ограничивают вас в плане структуры, но не ограничивают в плане функционала.
Возвращаясь к вопросу об MVC, можно заметить, что очень многие фреймворки используют именно такой подход: дают достаточно четкую структуру приложения, при которой происходит еще и деление файлов на виды, модели и контроллеры. Все это в совокупности способно сэкономить вам много времени, если вы однажды потратите его на то, чтобы научиться использовать фреймворк и модель MVC.
Среди других преимуществ модели MVC можно отметить разделение кода по функциональному признаку . Вам больше не нужно будет копаться в "каше" из SQL-запросов, разметки и PHP-кода. Если вам нужно что-то подправить или изменить, вы точно будете знать, какой именно файл вам надо править.
Ниже вы можете видеть часть файла, относящегося к группе "виды":
А вот кусок кода из модели:
Так может выглядеть контроллер:
Очень важным преимуществом, как вы видите, является отделение вида от кода . Зачастую необходимо так или иначе менять дизайн или даже структуру сайта, сохраняя при этом ту же самую информацию на странице, что выводилась и раньше. И тут начинается правка мешанины из кода, которая становится со временем все труднее и труднее.
Преимущество модели MVC заключается как раз в возможности полностью исключить правку дизайна сайта при изменении логики работы приложения . Вы можете менять любой из трех элементов: Модель, Вид, Контроллер. При этом вам не придется вносить изменения в другие элементы, так как они являются в известной степени автономными.
Особенно актуален вопрос автономности для моделей и видов. Однажды написав их, вы, как правило, можете с успехом использовать их для разных проектов, внося минимальные правки, либо не внося их вовсе. Это позволяет сэкономить вам много времени, избавляя от повторного написания похожего кода.
Очевидны преимущества применения модели MVC в рамках фреймворка , например, того же CodeIgniter.
Не секрет, что на каждом сайте есть большое количество похожих, а то и вовсе идентичных функций. Достаточно вспомнить форму обратной связи или постраничную навигацию. Это лишь наиболее яркие, "внешние" моменты. Еще больше сходств вы найдете в коде, который не виден обычному пользователю, в коде, который выполняется на сервере.
Практически все веб-разработчики сталкиваются с необходимостью использовать похожие функции PHP, производить похожие запросы к базе данных и т.п. Производители фреймворков сделали здесь очень важную вещь - они постарались сгруппировать те функции, которые применяются наиболее часто в отдельные файлы, предоставив вебмастерам и веб-программистам новые возможности.
Теперь можно выполнять часто необходимые вещи не особо задумываясь о том, какова их реализация. Можно писать пару строчек кода вместо пары десятков строчек, экономя свое время и больше сосредоточившись на логике работы приложения, а не на том, как это реализовать .
И все это происходит в рамках концепции MVC, позволяя вам добиваться практически любых результатов средствами фреймворка. При этом вы получаете высокую степень читаемости кода. А что еще нужно для комфортной и результативной работы?
Послесловие: Не забывайте о том, что любая структура, которая была создана для облегчения выполнения определенных задач, была создана именно для облегчения работы.
Не стоит придерживаться принципа MVC в тех случаях, когда вы уверены, что это плохо сказывается на вашем понимании структуры приложения. Не вы должны "прогибаться" под модель, а она под вас.
Дмитрий Науменко
P.S. Думаете, какой бы PHP-фреймворк освоить? Обратите внимание на CakePHP - он реализует рассмотренный выше паттерн MVC, и прямо сейчас вы можете получить небольшой вводный видеокурс, чтобы получить общее представление о возможностях этого фреймворка:
Понравился материал и хотите отблагодарить?
Просто поделитесь с друзьями и коллегами!
Контроллеры
Каждый запрос, поступающий в приложение, обрабатывается контроллером. Контроллер может обрабатывать запрос произвольным образом до тех пор, пока он не пересекает границу ответственности модели и представления. Это означает, что контроллеры не должны содержать или сохранять данные, равно как не генерировать пользовательские интерфейсы.
В инфраструктуре ASP.NET MVC Framework контроллеры являются классами.NET, которые содержат логику, требуемую для обработки запроса. Роль контроллера заключается в инкапсуляции логики приложения. Другими словами, контроллеры отвечают за обработку входящих запросов, выполнение операций над моделью предметной области и выбор представлений для визуализации пользователю.
Пример приложенияДля целей этой и следующих статей мы создадим новый проект MVC по имени ControllersAndActions с использованием шаблона Empty (Пустой), отметив флажок MVC в разделе Add folders and core references for (Добавить папки и основные ссылки для), а также проект модульного тестирования под названием ControllersAndActions.Tests. Модульные тесты, которые будут создаваться, не требуют имитированных реализаций, поэтому пакет Moq устанавливать не придется, но нужно установить пакет MVC, чтобы тесты имели доступ к базовым классам контроллеров.
В окне консоли диспетчера пакетов NuGet среды Visual Studio введите следующую команду:
Install-Package Microsoft.Aspnet.Mvc -version 5.0.0 -projectname ControllersAndActions.Tests
После создания проекта выберите пункт ControllersAndActions Properties (Свойства ControllersAndActions) в меню Project (Проект) среды Visual Studio, в открывшемся диалоговом окне перейдите на вкладку Web (Веб) и отметьте переключатель Specific Page (Определенная страница) в категории Start Action (Начальное действие). Вводить какое-либо значение не нужно - достаточно только выбора переключателя.
Понятие контроллераВы сталкивались со случаями использования контроллеров почти во всех предшествующих статьях, посвященных ASP.NET MVC. Наступило время заглянуть "за кулисы".
Создание контроллера с помощью интерфейса IControllerВ MVC Framework классы контроллеров должны реализовать интерфейс IController из пространства имен System.Web.Mvc , показанный в примере ниже:
Using System.Web.Routing; namespace System.Web.Mvc { public interface IController { void Execute(RequestContext requestContext); } }
Чтобы получить определение этого интерфейса, необходимо загрузить исходный код MVC Framework , который чрезвычайно полезен для выяснения внутренней работы средств инфраструктуры.
Как видите, интерфейс IController очень прост. Его единственный метод Execute() вызывается, когда запрос направляется этому классу контроллера. Инфраструктура MVC Framework выясняет, на какой класс ориентирован запрос, за счет чтения значения свойства controller, сгенерированного данными маршрутизации, или через специальные классы маршрутизации.
Создавать классы контроллеров можно путем реализации интерфейса IController, однако поскольку этот интерфейс является низкоуровневым, потребуется проделать немало работы, чтобы получить, в конечном счете, что-нибудь полезное. Тем не менее, интерфейс IController полезен для демонстрации оперирования контроллеров и с этой целью в папке Controllers создается новый файл класса по имени BasicController.cs, содержимое которого приведено в примере ниже:
Using System.Web.Mvc; using System.Web.Routing; namespace ControllersAndActions.Controllers { public class BasicController: IController { public void Execute(RequestContext requestContext) { string controller = (string)requestContext.RouteData.Values["controller"]; string action = (string)requestContext.RouteData.Values["action"]; requestContext.HttpContext.Response.Write(string.Format("Контроллер: {0}, Метод действия: {1}", controller, action)); } } }
Методу Execute() интерфейса IController передается объект RequestContext , предоставляющий информацию о текущем запросе и маршруте, который ему соответствует (и приводит к вызову данного контроллера для обработки этого запроса). В классе RequestContext определены два свойства, описанные в таблице ниже:
Объект HttpContextBase предоставляет доступ к набору объектов, описывающих текущий запрос, которые называются объектами контекста; мы еще вернемся к ним позже. Объект RouteData описывает маршрут. Важные свойства класса RouteData перечислены в таблице ниже:
В статье Настройка системы маршрутизации было показано, как использовать типы RouteBase и IRouteHandler для настройки системы маршрутизации. В рассматриваемом примере с помощью свойства Values получаются значения переменных сегментов controller и action, которые затем записываются в ответ.
Часть проблемы, возникающей при создании специальных контроллеров, связана с отсутствием доступа к таким средствам, как представления. Это означает, что придется работать на более низком уровне, чем и объясняется запись содержимого напрямую в ответ клиенту. Свойство HttpContextBase.Response возвращает объект HttpResponseBase , который позволяет конфигурировать и добавлять содержимое к ответу, предназначенному для отправки клиенту. Это еще одна точка соприкосновения между платформой ASP.NET и инфраструктурой MVC Framework.
Если запустить приложение и перейти на URL вида /Basic/Index, то специальный контроллер сгенерирует вывод, показанный на рисунке ниже:
Реализация интерфейса IController позволяет создать класс, который MVC Framework распознает как контроллер и отправляет ему запросы, безо всяких ограничений относительно того, как запрос обрабатывается, и какой ответ для него генерируется. Это удачный пример, поскольку он показывает, насколько расширяемой может быть инфраструктура MVC Framework даже для ключевых строительных блоков вроде контроллеров, однако написание сложного приложения подобным образом может быть сопряжено с немалыми трудностями.
Классы с именами, заканчивающимися на BaseПри обработке запросов инфраструктура MVC Framework полагается на платформу ASP.NET, что имеет большой смысл, т.к. эта платформа является проверенной и многофункциональной реализацией, которая тесно интегрируется с сервером приложений IIS. Проблема заключается в том, что классы, применяемые платформой ASP.NET для предоставления информации о запросах, не очень хорошо подходят для модульного тестирования - основного преимущества использования MVC Framework.
В Microsoft решили ввести возможность тестирования, поддерживая при этом совместимость с существующими приложениями ASP.NET Web Forms, так что в результате появились классы Base . Эти классы так называются из-за того, что они имеют те же самые имена, как у основных классов платформы ASP.NET, за которыми следует слово Base.
Так, например, платформа ASP.NET предоставляет контекстную информацию о текущем запросе и ряде ключевых служб приложения через объект HttpContext. Соответствующим ему классом Base является HttpContextBase, экземпляр которого передается методу Execute(), определенному в интерфейсе IController (в последующих примерах будут продемонстрированы и другие классы Base). В первоначальных классах и классах Base определены одни и те же свойства и методы, но классы Base всегда абстрактны , а это значит, что их легко применять для модульного тестирования.
Иногда вы получите экземпляр одного из первоначальных классов ASP.NET, такого как HttpContext. В таком случае необходимо создать дружественный к MVC класс Base, подобный HttpContextBase. Это делается с использованием одного из классов Wrapper , которые имеют такие же имена, как первоначальные классы, дополненные словом Wrapper, например, HttpContextWrapper . Классы Wrapper являются производными от классов Base и имеют конструкторы, которые принимают экземпляры первоначальных классов:
Первоначальные классы, классы Base и классы Wrapper определены в пространстве имен System.Web, поэтому платформа ASP.NET может гладко поддерживать приложения MVC Framework и более старые приложения Web Forms.
Создание контроллера за счет наследования от класса ControllerКак было продемонстрировано в предыдущем примере, инфраструктура MVC Framework допускает практически неограниченную настройку и расширение. Чтобы обеспечить любой требуемый вид обработки запросов и генерации результатов, можно реализовать интерфейс IController. Вам не нравятся методы действий? Вы не хотите беспокоиться по поводу визуализированных представлений? В таком случае можете взять дело в свои руки и реализовать лучший, быстрый и более элегантный способ обработки запросов. Либо же вы можете воспользоваться средствами, предлагаемыми командой разработчиков MVC Framework из Microsoft, и унаследовать свои контроллеры от класса System.Web.Mvc.Controller .
Класс Controller обеспечивает поддержку обработки запросов, которая знакома большинству разработчиков приложений MVC. Она применялась во всех примерах, рассмотренных в предыдущих статьях. Класс Controller предоставляет три ключевых средства, которые описаны ниже:
Методы действийПоведение контроллера разнесено по множеству методов (вместо реализации в виде единственного метода Execute()). Каждый метод действия отображается на соответствующий URL и вызывается с параметрами, извлеченными из входящего запроса.
Результаты действийМожно возвращать объект, описывающий результат выполнения действия (например, визуализация представления либо перенаправление на другой URL или метод действия), и затем обрабатывать его каким угодно образом. Разделение между указанием результатов и их выполнением упрощает модульное тестирование.
ФильтрыМногократно используемое поведение (например, аутентификацию) можно инкапсулировать в виде фильтров и затем помечать каждый аспект поведения контроллеров и методов действий с помощью атрибута в исходном коде.
Если только вы не имеете дело со специфичным требованием, то лучшим подходом к созданию контроллеров будет их наследование от класса Controller, что, как и можно было ожидать, делает среда Visual Studio, когда создает новый класс в ответ на выбор пункта меню Add --> Scaffold (Добавить --> Шаблон).
В примере ниже приведен код простого контроллера под названием DerivedController, созданного подобным образом. Он сгенерирован с применением варианта MVC 5 Controller - Empty (Контроллер MVC 5 - Пустой) с несколькими простыми изменениями, предназначенными для установки свойства ViewBag и выбора представления:
Using System; using System.Web; using System.Web.Mvc; namespace ControllersAndActions.Controllers { public class DerivedController: Controller { public ActionResult Index() { ViewBag.Message = "Привет из контроллера DerivedController метода действия Index"; return View("MyView"); } } }
Класс Controller также обеспечивает связь с системой представлений Razor. В этом примере мы возвращаем результат вызова метода View(), которому в качестве параметра передается имя представления для визуализации клиенту. Чтобы создать это представление, создайте папку Views/Derived, щелкните на ней правой кнопкой мыши и выберите в контекстном меню пункт Add --> MVC 5 View Page (Razor) (Добавить --> Страница представления MVC 5 (Razor)). Укажите в качестве имени MyView.cshtml и щелкните на кнопке ОК для создания файла представления.
Приведите содержимое файла в соответствие с примером:
@{ ViewBag.Title = "Index"; } MyView Сообщение от контроллера: « @ViewBag.Message »
После запуска приложения и перехода на URL вида /Derived/Index этот метод действия вызывается, а представление MyView визуализируется:
Наследование от класса Controller приводит к необходимости в реализации методов действий, получении любых входных данных, необходимых для обработки запроса, и генерации подходящего ответа. В следующих статьях описано множество подходов, позволяющих делать это.
Принцип MVC у веб-программировании (Model - View - Controller, Модель - Представление(Вид) - Контроллер) - одна из наиболее удачных идей на сегодняшний день. Принцип MVC интуитивно понятен на первый взгляд, но не очень простой при углублении. Сначала рассмотрим, для чего он предназначен.
Принцип MVC , позволяет разделить реализацию логики приложения, внешний вид (графический интерфейс, GUI) и взаимодействие с пользователем.
Это приводит к более структурированном коде, позволяет работать над проектом более специализированным людям, упрощает поддержку кода, делает его более логичным и понятным. Изменение в одном из компонентов минимально влияет на остальные. Можно к одной модели подключать разные виды, разные контроллеры.
С другой стороны, это требует большей производительности исполняющих машин, но в последнее время это не есть большой проблемой - все более сложные программистские решения требуют поддержки, и затраты на поддержку намного превысят затраты на более мощное современное оборудование.
Принцип MVC используют практически все современные фреймворки.
Рассмотрим подробнее компоненты.
Model (Модель) - содержит т.н. "бизнес-логику" - обработку и верификацию данных, обращения к базам данных, представляет внутреннее устройство системы. Модель не должна напрямую взаимодействовать с пользователем.
View (Вид, Представление) описывает внешний вид приложения.
Controller (Контроллер) - связующее звено между моделлю и видом, получает данные от пользователя, передает их модели, получает обработанный результат и передает его в представление.
Взаимосвязь можно посмотреть на диаграмме:
Источник изображения: http://www.wikipedia.org Требования к компонентам:
Модели:
Кроме концепции MVC существуют и многие другие, например MOVE ( M odels, O perations, V iews и E vents) - вроде, как эволюция MVC (взято отсюда: http://habrahabr.ru/post/147038/), но эти концепции менее распространенные.