Паттерн проектирования MVC
Доброго времени суток, мои маленькие программисты. Сегодня мы разберем такую важную тему, как шаблон проектирования MVC (Model-View-Controller - Модель-представление-контроллер). Я думаю, вы все уже знаете. что это за шаблон и для чего он нужен. Для танкистов напомню, что он служит для отделения логики от представления, т.е. разделяет труд программера и верстальщика. А как известно, разделение труда это круто :). Итак, понеслась.
Я долго не мог понять этот паттерн. Гуглил, читал блоги, но реализацию паттерна представлял смутно. В основном этот шаблон объясняют на примере ООП, но применять его можно и в процедурном подходе. Разберем каждую часть паттерна:
- Модель. Модель это логика приложения или как модно говорить - бизнес-логика. Здесь происходит взаимодействие с хранилищем данных (БД, файлы). Модель по-идее взаимодействует только с контроллером, а о существовании вьюшки даже и не подозревает.
- Контроллер. Контроллер это как бы обработчик. Здесь происходит обработка данных, фильтрация, etc. Вот он может взаимодействовать и с моделью, получая из нее данные, и с вьюхой, отправляя их туда.
- Представление. Представление это простой шаблон со вставками данных. Здесь должно быть по минимуму программного кода.
Но теория теорией, пора переходить и к практике. Мы с вами разработаем небольшую страничку с выводом постов, эдакий мини-блог :). Поехали (c).
Для начала создадим конфигурационный файл, куда занесем данные о подключении к БД (MySQL):
<?php
/**
* Файл конфигурации.
*
* Здесь можно определить различные константы, например путь к сайту, etc
*
* @author Канат Гайлимов, http://gailimov.info
*/
$dbHost = "localhost";
$dbUser = "root";
$dbPass = "";
$dbName = "mvc";
// по хорошему вместо "дая" должны быть исключения, но для примера "дай" сойдет :)
mysql_connect($dbHost, $dbUser, $dbPass) or die("MySQL не доступен! ".mysql_error());
mysql_select_db($dbName) or die("Нет соединения с базой данных! ".mysql_error());
mysql_query("SET NAMES utf8") or die("Невозможно установить кодировку! ".mysql_error());
/* Конец файла ./config.php */
Тпереь создадим SQL-схему таблицы постов. В архиве (ниже), вы найдете инсталяшку (рыбу лучше не читать, можете взорвать мозг :).
CREATE TABLE IF NOT EXISTS `posts` (
`id` INT(4) NOT NULL AUTO_INCREMENT,
`title` VARCHAR(255) NOT NULL,
`blog_post` TEXT NOT NULL,
`dt` DATETIME NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 ;
Ну и модель:
<?php
/**
* Это модель, так сказать бизнес-логика
*
* Модель должна взаимодействовать только с контроллером, а на вьюшку ей пох :)
* Можно вместо мускула заюзать скуллайт или даже текстовые файлы.
* Самые крутики могут прикрутить PDO :)
*
* @author Канат Гайлимов, http://gailimov.info
*/
/**
* Функция селектит посты из БД
*
* @return array
*/
function getPosts()
{
$q = "SELECT * FROM posts ORDER BY dt DESC, id DESC";
$res = mysql_query($q) or die(mysql_error());
$posts = array();
while ($row = mysql_fetch_assoc($res)) {
$posts[] = $row;
}
return $posts;
}
/* Конец файла ./mposts.php */
Контроллер:
<?php
/**
* Это контроллер
*
* Здесь происходит обработка переменных, фильтрация и тыды.
* Контроллер взаимодействует с моделью и вьюшкой
*
* @author Канат Гайлимов, http://gailimov.info
*/
require_once 'config.php';
require_once 'mposts.php';
$posts = getPosts();
include_once 'vposts.php';
/* Конец файла ./cposts.php */
И вьюшка (валидный HTML 5 :)):
<!doctype html>
<html>
<head>
<meta charset=utf-8>
<!--[if IE]>
<script>
document.createElement('header');
document.createElement('nav');
document.createElement('section');
document.createElement('article');
document.createElement('aside');
document.createElement('footer');
</script>
<![endif]-->
<link rel="stylesheet" href="style.css" type="text/css" media="screen" />
<title>Пример применения паттерна проектирования MVC</title>
</head>
<body>
<div id="wrapper">
<header id="head">
<h1>Мини-блог с применением MVC</h1>
</header>
<section>
<?php foreach ($posts as $post) : ?>
<article>
<header>
<h2><?=$post['title']?></h2>
</header>
<?=$post['blog_post']?>
<p class="date"><?=$post['dt']?></p>
</article>
<?php endforeach ?>
</section>
<footer>
<p>© <a href="http://gailimov.info">Канат Гайлимов</a> <?=date('Y')?></p>
</footer>
</div>
</body>
</html>
Как видите мы использовали короткую запись оператора foreach, это очень удобно. Также мы использовали короткую запись <?=$var?>. Вы же можете писать <?php echo $var ?>, т.к. рекомендовано в документации. Или можно вообще прикрутить какой-нибудь шаблонизатор, например тот же Smarty. Может быть я даже покажу это в следующих постах :).
Ну и напоследок создадим файл index.php, который будет подгружать контроллеры.
<?php
/**
* Загрузчик контроллеров
*
* @author Канат Гайлимов, http://gailimov.info
*/
require_once 'cposts.php';
На этом все. Думаю понтно обьяснил :). Здесь вы можете скачать архив с этим примером и самостоятельно потренироваться. Вопросы/пожелания/критику постить в комментах. Бай-бай :).
Запостено: 15 августа 2010 г. в 14:02 | 18 комментов














Комменты:
#1 Никита Красноярцев
Самому разбираться всё времени не было, а тут всё просто и понятно, спасибо=)
Добавлено: 15 августа 2010 г. в 15:00
Ответить
#2 Канат Гайлимов
@Никита Красноярцев, с тебя объяснение ООП
Добавлено: 15 августа 2010 г. в 15:06
Ответить
#3 Никита Красноярцев
@Канат Гайлимов, Хорошая мысль=) Главное найти время для статьи)) ПС: У тебя подсветка синтаксиса в блоге на JavaScript чтоли работает? Я заметил сначала код загружается без оформления, и только потом подсвечивается...
Добавлено: 15 августа 2010 г. в 16:04
Ответить
#4 Канат Гайлимов
Да, это скрипт от Ивана Сагалаева highlight.js. Подсветка на JS не нагружает сервак
Добавлено: 15 августа 2010 г. в 17:02
Ответить
#5 Fish
Жесть. Это просто луч поноса в сторону GoF.
Добавлено: 15 августа 2010 г. в 22:09
Ответить
#6 Rex
хм. У меня MVC всегда ассоциировалось с ООП. Советую именно с учетом его и работать. Можете написать небольшой мини-фрейморк по теме - это будет довольно познавательно.
Добавлено: 16 августа 2010 г. в 07:14
Ответить
#7 Канат Гайлимов
А пояснить? Кстати GoF уже заказал
@Rex, да собираюсь вплотную заняться изучением ООП, планирую заюзать CodeIgniter для начала
Ну или да, может напишу для себя мини-фреймворк 
Добавлено: 16 августа 2010 г. в 10:44
Ответить
#8 Fish
Посмотрите архитектуру любого серьёзного MVC-фреймворка и вы поймете, что я имею в виду. Не знаю, есть ли что-то достойное на PHP, но на других языках - ASP.NET MVC, Spring MVC (Java), да хоть тот же Ruby On Rails
Добавлено: 17 августа 2010 г. в 08:53
Ответить
#9 Канат Гайлимов
@Fish, ну этим постом я хотел показать как можно применять MVC и в процедурном PHP, его общую суть. А "серьезные MVC-фреймворки" я обязательно посмотрю в будущем
Добавлено: 17 августа 2010 г. в 13:07
Ответить
#10 Orlenko K.N.
Пасиба, Канат, за статью, тоже начал с ООП разгребаться, как раз пример кстати будет
Добавлено: 18 августа 2010 г. в 18:33
Ответить
#11 DarkwaveMD
отличное объяснение принципов MVC, и , что самое главное, наглядное) У Вас прям зачатки педагога просматриваются)
Добавлено: 18 августа 2010 г. в 18:54
Ответить
#12 Канат Гайлимов
@Orlenko K.N., на здоровье
Даа, ООП весчь, но MVC можно юзать и в процедурном подходе, что собственно и показано
@DarkwaveMD, спасибо )) буду развивать их 
Добавлено: 19 августа 2010 г. в 13:17
Ответить
#13 saint_byte
Ну кто теперь этого патерна не знает =))))) ИХМО основная проблема в этом патерне именно в разделение что и куда , а то бывает модель и контроллер начинают содержать части друг друга =)
Добавлено: 24 августа 2010 г. в 14:43
Ответить
#14 Канат Гайлимов
@saint_byte, ну при грамотном использовании, все должно находиться на своих местах
Добавлено: 30 августа 2010 г. в 10:20
Ответить
#15 CrashX
это не MVC, больше на MVP похоже
Добавлено: 29 сентября 2010 г. в 11:24
Ответить
#16 stopkran
Это отличный пример mvc. А то pft..ли уже всякие умники из ООП. Ясиры Арафаты, блин. Единственное слабое место (сразу бросается в глаза):
<?=$post['blog_post']?>
Откуда "Представление" знает о том, что там надо писать именно "блок_пост"? Вот для ликвидации этой "магии" как раз и придётся подымать уровень до ф-ций или классов, усложнять конструкцию.
Добавлено: 26 июня 2011 г. в 13:56
Ответить
#17 Канат Гайлимов
@stopkran, спасибо, это был самый простой вариант "MVC для самых маленьких"
Не совсем понял, что тут плохого
Представление не знает, а вот разработчик знает
Добавлено: 27 июня 2011 г. в 08:42
Ответить
#18 Иван
Ну данный подход сложно назвамть патерном проектирования MVC, хотя общий принцип можно проследить
Добавлено: 17 сентября 2011 г. в 00:43
Ответить