Разделение кода и шаблона, MVC — Часть II

Разделение кода и шаблона, MVC — Часть 2
Что же такое MVC? В переводе с английского, это означает «Модель-Представление-Контроллер». Первым делом, для наглядности, я приведу иллюстрацию концепции MVC и иллюстрацию иерархии файлов при использовании этой технологии:

Концепция MVC
Концепция MVC
Иерархия файлов при использовании MVC
Иерархия файлов при использовании MVC

Для простоты, в дальнейшем файлы будем называть так:

  • index.php — Контроллер;
  • model.php — Модель;
  • shablon.html — Представление.

В папке /tpl хранятся все шаблоны (дизайны) нашей страницы. В папке /img — все используемые изображения.

В общем и самом простом случае данная архитектура состоит из трёх файлов, каждый из которых и отвечает за конкретную букву в аббревиатуре MVC. Главный файл — файл, расположенный в корне — index.php. Этот файл будет автоматически запускаться, если пользователь зайдёт в корневую директорию. Файл index.php — это контроллер, отвечающий за обработку действий пользователя, например, нажатие кнопок в формах, вызов различных функций и подключение шаблона. Обычно, этот файл имеет небольшой размер и содержит лишь вызовы функций. Все пользовательские функции выносятся в файл model.php. Этот файл представляет собой набор этих функций — библиотеку. Ничего кроме них там не содержится.

Чтобы использовать функции из model.php в начало кода файла index.php вставляется строка, подключающая эту библиотеку:

include “model.php”;

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

Файл же index.php обрабатывает переданные POST и GET запросами параметры, введённые в формы пользователем данные и в зависимости от условий запускает различные функции из модели, которые, в свою очередь, генерируют данные для Представления. Стоит заметить, что ни index.php, ни model.php не выводят ни строчки кода, т. е. внутри этих файлов не встречаются echo и print. Почему так? В этом же и есть принцип разделения кода и дизайна. Ведь если, скажем, в Модели будет функция, которая будет выводить какой-либо текст и когда-то дизайнеру понадобится её «задизайнить», добавив, например,

<div class="…"></div>

к этому самому тексту, ему придётся, проклиная программиста, искать, где эта строчка находится в php-файлах.

Вот и получается, что Контроллер в зависимости от различных обстоятельств (параметры, нажатость различных кнопок на страницах, статус юзера и т. д.) вызывает различные, нужные для данных обстоятельств функции из библиотеки функций — Модуля, который формирует данные для Вида. А Вид, являющийся по своей сути простым html-документом со вставками php-переменных в нужных местах, получив все данные от Модели, формирует внешний вид страницы, в конечном счете, получаемой пользователем.

В чём суть такого разделения? Во-первых, все шаблоны верстальщик пишет сам, не задумываясь над тем, как и что реализует программист. Им лишь нужно согласовать все переменные и массивы, которые верстальщик должен будет вставить в html-код страницы. На этом углубление в дебри php-кодинга для верстальщика заканчивается;) Во-вторых, все функции вынесены в отдельный файл, что позволяет всегда легко и удобно их править/добавить/удалить. В-третьих, логика всего приложения находится в файле index.php (Контроллер). Логика, её ещё часто называют Бизнес-логикой, является «сердцем» скрипта. Именно она решает, что именно Ваш код должен сделать. Очень удобно, когда логика не захламлена элементами дизайна и функциями. Ну и к четвёртому плюсу данной технологии можно отнести возможность Контроллера в зависимости от каких-либо обстоятельств загрузить другой шаблон, поменяв при этом дизайн страницы.

Попробую теперь объяснить суть MVC на примере. Представьте, что у нас есть страничка, на которой находится некая новость и, например, пять комментариев пользователей. Пускай адрес этой страницы будет true-coder . ru /. То есть, сам файл имеет имя index.php. Это наш Контроллер. На страницу можно зайти с правами гостя, обычного пользователя и администратора. Если на страницу зайдёт администратор, справа от контентной части будет располагаться некая статистика, а под каждым комментарием пользователей — ссылка на удаление. Ни первого, ни второго в браузере обычного пользователя видно не будет. А в браузере гостя не будет даже комментариев. Поэтому, наш дизайнер рисует три варианта этой страницы с разным функционалом, верстальщик создаёт три html-файла, соответственно. В итоге, мы получаем файлы, которые назовём, например shablon1.html, shablon2.html и shablon3.html, которые, как на картинке выше, поместим в папку /tpl. Теперь займёмся Моделью. Функций там может быть много, но мы опишем лишь те, которые важны для данного примера. Скажем, нам нужно написать функцию для получения из базы данных текста новости (новость будет зависеть от параметра id, передаваемого в GET-запросе: true-coder . ru /?id=3), функцию для вывода комментариев, функцию для удаления комментария, а также функцию для вывода статистики для администратора.

Назовём их следующим образом:

  • Show_News() — функция для вывода новости;
  • Comments() — функция для вывода комментариев;
  • Delete_Comment() — функция для удаления комментария;
  • Stat() — функция для вывода статистики.

Напомню, что в теле функции не должно быть ни одного вывода информации, функция должна просто возвращать переменную или массив обратно в контроллер. Запустив файл index.php, она проверит, какое значение параметра id Вы ей передали. Пусть, для примера, это будет 5. Узнав id, Контроллер запустит функцию Show_News(), которая вернёт переменную, например, $news с текстом новости. Далее, Контроллер проверит Ваши права на сайте — являетесь Вы гостем, зарегистрированным пользователем или админом. Предположим, что проверяет он, используя cookie (брутальный вариант, но для примера подойдёт). Если Вы — гость, то Контроллер больше не будет трогать Модель, т. е. не запустит ни одной функции и больше никаких данных сгенерировано не будет. Если же Вы зарегистрирован на сайте, то дополнительно вызовем функцию Comments(), которая вернёт массив $comments с комментариями. Если же Вы ещё и админ, то запустим функцию Stat(), которая вернёт массив $stat со статистикой. И осталась не затронутой одна функция — Delete_Comment(), которая удаляет один комментарий. Чтобы она была вызвана, Контроллер должен инициализировать Вас как админа, а также должен быть передан параметр, скажем, del. Пример: true-coder . ru /?del=4. Если Вы админ и параметр del был передан Контроллеру, то он запустит функцию Delete_Comment(), которая удалит комментарий с id, равным 4.

В зависимости от статуса пользователя (гость, обычный пользователь или админ), дизайн страницы будет различным. Какой файл шаблона подключить, решает также Контроллер. Если Вы простой гость, то он выведет дизайн лишь с переменной $news, на место которой вставится сгенерированный функцией Show_News() текст новости. Если Вы зарегистрированы, то подключится дизайн с новостью и циклом для вывода массива $comments. А если Вы — админ, то шаблон будет содержать блок со статистикой и ссылки для удаления под каждым комментарием. Вот кстати, большой плюс в использовании технологии MVC – можно на лету возвращать различные по функционалу и внешнему виду страницы, доступные по одному адресу.

Псевдокод Модели (model.php) выглядит так:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
<?
function Show_News($id)
	{return $news;
}
function Comments()
	{return $comments;
}
function Delete_Comment($id)
	{return true;
}
function Stat()
	{return $stat;
}
?>
 
Псевдокод Контроллера (index.php) выглядит так:
<?
If (Вы – гость)
	{
	$news= Show_News($id);
	}
If (Вы – зарегистрированный пользователь)
	{
	$news= Show_News($id);
	$comments= Comments();
	}
If (Вы – админ)
	{
	$news= Show_News($id);
	$comments= Comments();
	$stat=Stat();
	}
If (isset($_GET[del] &#038;& Вы админ)
	{
	function Delete_Comment($_GET[del]);
	$news= Show_News($id);
	$comments= Comments();
	$stat=Stat();
	}
//в зависимости от Вашего статуса подгружаем нужный файл шаблона
If (Вы – гость)
	{
	include/tpl/shablon1.html”;
	}
If (Вы – зарегистрированный пользователь)
	{
	include/tpl/shablon2.html”;
	}
If (Вы – админ)
	{
	include/tpl/shablon3.html”;
	}
?>

В файле шаблонов будут выводиться лишь нужные переменные. В файле-шаблоне для гостей — только переменная $news, а в файле-шаблоне для зарегистрированных юзеров — ещё и массив $comments.

Выводятся, например, таким образом:

1
2
3
4
5
6
7
<?=$news;?> - вывод переменных;
<?
foreach ($comments as $v)
	{
	echo $v.””;
	}
?>

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

Оставайтесь с нами 🙂

Разделение кода и шаблона, MVC — Часть I

  • Сергей

    Спасибо за простое и полное изложение принципа MVC! Под полным я имею в виду пример распределения кода по файлам и расположение этих файлов в файловой стркутуре, плюс — логика работы.

  • Сергей, пожалуйста, рады стараться) Данный пример не является, так сказать, лучшим способом представления MVC, однако по этому принципу работа упрощается в десяток раз. Дизайнеру, верстальщику, кодеру намного удобнее становится работать, а их «соприкосновение» происходит достаточно редко. Мы и сами работаем абсолютно по такой же схеме.

  • Сергей

    Да, Вы правы. Я только начал изучать этот подход. А не могли бь Вы подсказать, как, в рамках этой модели, использовать собственные файлы стилей?
    Я пробую такой способ, но не он не работает:

    $document =& JFactory::getDocument();
    $document->addStyleSheet(«http://сайт/joomla/components/com_tabel/views/tabel/tmpl/tabel.css»);

    Ссылка на мой стиль не добавляется в тэг HEAD моего компонента.

  • Я, конечно, не специалист по Jooml’е, но Вы, по-моему, всё делается верно. Внимательно проверьте путь к css-файлу, возможно, что Вы опечатались или указываете неправильный путь.

  • Сергей

    Я нашёл, все-таки, причину: эти строки нужно было вставить в функцию, в файле модели (\components\com_tabel\models\tabel.php), а я вставлял их в файл шаблона (\components\com_tabel\views\tabel\tmpl\default.php).
    Спасибо за отклик!

  • Настенька

    «Мы и сами работаем абсолютно по такой же схеме» заставляет улыбнуться
    а как давно вы используете мвц?

    • С первого серьёзного нашего проекта. То есть, около года.

      • Напишите пожалуйста про HMVC, желательно на ООП. Эта тема очень слабо развита, в интернете всего 2 нормальные статьи нашёл, но там одна теория, практического нет ничего.

  • Уважаемый Загорцев Андрей.
    Я очень благодарен Вам за статью MVC вы открыли для меня много непонятного в этой архитектуре и если у вас есть что то добавить то продолжайте уроки в этом направлении и если можно то сделайте примеры сайта интернет магазина или обычный блог с полной MVC.

  • Андрей

    Спс за интересную статью

  • Жора КорТнев

    без потовая статья