RSS-фид

Паттерн проектирования 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 комментов

Комменты:

#3 Никита Красноярцев

Никита Красноярцев

@Канат Гайлимов, Хорошая мысль=) Главное найти время для статьи)) ПС: У тебя подсветка синтаксиса в блоге на JavaScript чтоли работает? Я заметил сначала код загружается без оформления, и только потом подсвечивается...

Добавлено: 15 августа 2010 г. в 16:04

Ответить

#4 Канат Гайлимов

Канат Гайлимов

Да, это скрипт от Ивана Сагалаева highlight.js. Подсветка на JS не нагружает сервак

Добавлено: 15 августа 2010 г. в 17:02

Ответить

#5 Fish

Fish

Жесть. Это просто луч поноса в сторону GoF.

Добавлено: 15 августа 2010 г. в 22:09

Ответить

#6 Rex

Rex

хм. У меня MVC всегда ассоциировалось с ООП. Советую именно с учетом его и работать. Можете написать небольшой мини-фрейморк по теме - это будет довольно познавательно.

Добавлено: 16 августа 2010 г. в 07:14

Ответить

#7 Канат Гайлимов

Канат Гайлимов

Жесть. Это просто луч поноса в сторону GoF.

А пояснить? Кстати GoF уже заказал @Rex, да собираюсь вплотную заняться изучением ООП, планирую заюзать CodeIgniter для начала Ну или да, может напишу для себя мини-фреймворк

Добавлено: 16 августа 2010 г. в 10:44

Ответить

#8 Fish

Fish

А пояснить? Кстати GoF уже заказал

Посмотрите архитектуру любого серьёзного 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.

Orlenko K.N.

Пасиба, Канат, за статью, тоже начал с ООП разгребаться, как раз пример кстати будет

Добавлено: 18 августа 2010 г. в 18:33

Ответить

#11 DarkwaveMD

DarkwaveMD

отличное объяснение принципов MVC, и , что самое главное, наглядное) У Вас прям зачатки педагога просматриваются)

Добавлено: 18 августа 2010 г. в 18:54

Ответить

#12 Канат Гайлимов

Канат Гайлимов

@Orlenko K.N., на здоровье Даа, ООП весчь, но MVC можно юзать и в процедурном подходе, что собственно и показано @DarkwaveMD, спасибо )) буду развивать их

Добавлено: 19 августа 2010 г. в 13:17

Ответить

#13 saint_byte

saint_byte

Ну кто теперь этого патерна не знает =))))) ИХМО основная проблема в этом патерне именно в разделение что и куда , а то бывает модель и контроллер начинают содержать части друг друга =)

Добавлено: 24 августа 2010 г. в 14:43

Ответить

#15 CrashX

CrashX

это не MVC, больше на MVP похоже

Добавлено: 29 сентября 2010 г. в 11:24

Ответить

#16 stopkran

stopkran

Это отличный пример mvc. А то pft..ли уже всякие умники из ООП. Ясиры Арафаты, блин. Единственное слабое место (сразу бросается в глаза):

<?=$post['blog_post']?>

Откуда "Представление" знает о том, что там надо писать именно "блок_пост"? Вот для ликвидации этой "магии" как раз и придётся подымать уровень до ф-ций или классов, усложнять конструкцию.

Добавлено: 26 июня 2011 г. в 13:56

Ответить

#17 Канат Гайлимов

Канат Гайлимов

@stopkran, спасибо, это был самый простой вариант "MVC для самых маленьких"
Представление не знает, а вот разработчик знает Не совсем понял, что тут плохого

Добавлено: 27 июня 2011 г. в 08:42

Ответить

#18 Иван

Иван

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

Добавлено: 17 сентября 2011 г. в 00:43

Ответить

Оставить коммент:

Уважаемые посетители! Вы можете оставить свой коммент к этому посту. Пожалуйста, соблюдайте нормы приличия и этики.

Улыбка Убей себя ап стену :) Но-но-но! Лепота... Уррряя! В натуре Подмигиваю Ну извините... Ржунимагу Выпьем, друг! SOS Речь Бубен 0_o