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

И так начнем, как я уже писал в предыдущей статье, паттерн MVC подразумевает одну точку входа – index.php, через это скрипт будут проходить все запросы, через него будет работать вся логика проекта. Для того чтобы реализовать такой подход необходимо настроить сервер, подразумевается, что сайт работает на сервере apache, поэтому нам достаточно создать файл.htaccess, в котором мы укажем правила маршрутизации URL. Помимо определения точки входа, маршрутизация позволяет создавать ЧПУ(человеко-понятные урлы). То есть после правильной настройки, адреса страниц буду выглядеть вот так site.ru/article/new.
Для начала, давайте составим.htaccess, который перенаправит обработку всех страниц на скрипт index.php. Код выглядит вот так:

RewriteEngine on RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d RewriteRule ^(.*)$ index.php?route=$1

Файл.htaccess должен лежать в корневой папке сайта, тут же необходимо создать скрипт index.php, который является точкой входа. Давайте запишем в index.php одну строку, для проверки работы перенаправления:

Echo "test";

Теперь можно проверять работу перенаправления, введите любой адрес и посмотрите, что получиться: test-mvc.web/sdf/sdf/ или test-mvc.web/sdf/sdf/2342/не важно, на экране в любом случае, должно появиться «Test». Если Вы увидели эту надпись, значит, у нас все получилось.
Продолжим, давайте для удобства создадим в корне сайта файл config.php, в котором будем задавать различные константы, облегчающие своим существование настройку сайта. Это могут быть различные пути к скриптам, подступы к базе данных и так далее. Сейчас в конфиге давайте зададим следующее:

// Задаем константы: define ("DS", DIRECTORY_SEPARATOR); // разделитель для путей к файлам $sitePath = realpath(dirname(__FILE__) . DS); define ("SITE_PATH", $sitePath); // путь к корневой папке сайта // для подключения к бд define("DB_USER", "root"); define("DB_PASS", ""); define("DB_HOST", "localhost"); define("DB_NAME", "blog_mvc");

Для того, чтобы константы и другие данные конфига мы могли использовать во всем проекте, в файле index.php необходимо подключить скрипт config.php.
Помимо подключения файла с настройками, в index.php нужно создать подключение к базе данных, подключить скрипт с ядром сайта и запустить роутер, в котором будет происходить маршрутизация.
Теперь по порядку, создание соединения с базой данных будет находиться в index.php для того, чтобы соединение открывалось только один раз. Единожды открыв соединение, мы сможем использовать его во всех контроллерах и моделях, но об этом чуть позже. Сейчас просто создадим соединение с базой. Для работы с бд я решил использовать PDO. Подробнее почитать про PDO можно .
Ядро сайта расположим в папке core и назовем скрипт core.php, тут мы напишем функцию, которая будет сама подключать, необходимы для работы классы. Такая функция очень облегчит и упростит нам работу с контролерами, моделями и тд. Поскольку, забегая вперед скажу, что каждый контролер и каждая модель будут представлять собой отдельный класс.
Помимо авто подключения классов, добавим в ядро создания хранилища (реестра), в котором будем хранить все необходимые объекты и переменные, которые могут пригодиться в любом месте проекта.
Роутер тоже подключим в индексном файле, он будет анализировать URL и подключать необходимый контроллер и экшен. Что такое контролер я писал в предыдущей статье, а информацию про экшен я пропустил умышленно, не став нагружать лишней информацией. Так что же такое экшен?
Контролер это класс, в котором заключены различные методы, при MVC подходе каждый метод будет являться экшеном. То есть экшен(action) – это метод класса, который будет обрабатывать данные и передавать их в представление (в шаблон). Может быть, пока не совсем понятно, но после примера все станет на свои места.
На данном этапе теории достаточно, давайте перейдем к практике. Приведу код файлов, работу которых, я описывал выше.
Код скрипта index.php:

// включим отображение всех ошибок error_reporting (E_ALL); // подключаем конфиг include ("/config.php"); // Соединяемся с БД $dbObject = new PDO("mysql:host=" . DB_HOST . ";dbname=" . DB_NAME, DB_USER, DB_PASS); // подключаем ядро сайта include (SITE_PATH . DS . "core" . DS . "core.php"); // Загружаем router $router = new Router($registry); // записываем данные в реестр $registry->set ("router", $router); // задаем путь до папки контроллеров. $router->setPath (SITE_PATH . "controllers"); // запускаем маршрутизатор $router->start();

Скрипт core.php:

// Загрузка классов "на лету" function __autoload($className) { $filename = strtolower($className) . ".php"; // определяем класс и находим для него путь $expArr = explode("_", $className); if(empty($expArr) OR $expArr == "Base"){ $folder = "classes"; }else{ switch(strtolower($expArr)){ case "controller": $folder = "controllers"; break; case "model": $folder = "models"; break; default: $folder = "classes"; break; } } // путь до класса $file = SITE_PATH . $folder . DS . $filename; // проверяем наличие файла if (file_exists($file) == false) { return false; } // подключаем файл с классом include ($file); } // запускаем реестр (хранилище) $registry = new Registry;

Класс хранилища Registry.php, будет находиться в папке /classes/

// Класс хранилища Class Registry { private $vars = array(); // запись данных function set($key, $var) { if (isset($this->vars[$key]) == true) { throw new Exception("Unable to set var `" . $key . "`. Already set."); } $this->vars[$key] = $var; return true; } // получение данных function get($key) { if (isset($this->vars[$key]) == false) { return null; } return $this->vars[$key]; } // удаление данных function remove($var) { unset($this->vars[$key]); } }

Код файла router.php, который находиться в папке /classes/

// класс роутера Class Router { private $registry; private $path; private $args = array(); // получаем хранилище function __construct($registry) { $this->registry = $registry; } // задаем путь до папки с контроллерами function setPath($path) { $path = trim($path, "/\\"); $path .= DS; // если путь не существует, сигнализируем об этом if (is_dir($path) == false) { throw new Exception ("Invalid controller path: `" . $path . "`"); } $this->path = $path; } // определение контроллера и экшена из урла private function getController(&$file, &$controller, &$action, &$args) { $route = (empty($_GET["route"])) ? "" : $_GET["route"]; unset($_GET["route"]); if (empty($route)) { $route = "index"; } // Получаем части урла $route = trim($route, "/\\"); $parts = explode("/", $route); // Находим контроллер $cmd_path = $this->path; foreach ($parts as $part) { $fullpath = $cmd_path . $part; // Проверка существования папки if (is_dir($fullpath)) { $cmd_path .= $part . DS; array_shift($parts); continue; } // Находим файл if (is_file($fullpath . ".php")) { $controller = $part; array_shift($parts); break; } } // если урле не указан контролер, то испольлзуем поумолчанию index if (empty($controller)) { $controller = "index"; } // Получаем экшен $action = array_shift($parts); if (empty($action)) { $action = "index"; } $file = $cmd_path . $controller . ".php"; $args = $parts; } function start() { // Анализируем путь $this->getController($file, $controller, $action, $args); // Проверка существования файла, иначе 404 if (is_readable($file) == false) { die ("404 Not Found"); } // Подключаем файл include ($file); // Создаём экземпляр контроллера $class = "Controller_" . $controller; $controller = new $class($this->registry); // Если экшен не существует - 404 if (is_callable(array($controller, $action)) == false) { die ("404 Not Found"); } // Выполняем экшен $controller->$action(); } }

Теперь необходимо создать папки для хранения контроллеров, шаблонов и моделей – в корне создадим три папки controllers, views и models. И создадим несколько тестовых файлов /controllers/index.php, /views/index/index.php и /models/model_users.php, а теперь заполним файлы:
Для контроллера:

// контролер Class Controller_Index Extends Controller_Base { // шаблон public $layouts = "first_layouts"; // экшен function index() { $model = new Model_Users(); $userInfo = $model->getUser(); $this->template->vars("userInfo", $userInfo); $this->template->view("index"); } }

Для отображения(/views/index/index.php)

Test view
id:
name:

И модель:

// модель Class Model_Users{ public function getUser(){ return array("id"=>1, "name"=>"test_name"); } }

Как вы могли заметить, класс контролера наследуется от родительского класса Controller_Base. Это сделано, для того, чтобы упростить класс контролера. Поскольку нам еще необходимо подключать класс для работы с шаблонами, его подключение вынесено в Controller_Base.
Приведу его код, он расположен в папке /classes/ и называется controller_base.php:

// абстрактый класс контроллера Abstract Class Controller_Base { protected $registry; protected $template; protected $layouts; // шаблон public $vars = array(); // в конструкторе подключаем шаблоны function __construct($registry) { $this->registry = $registry; // шаблоны $this->template = new Template($this->layouts, get_class($this)); } abstract function index(); }

Теперь осталось только разобраться с шаблонами. В абстрактном классе Controller_Base мы вызываем класс Template и передаем ему имя шаблона и имя контроллера.
Код класса Template, который лежит тут /classes/ и называется template.php

// класс для подключения шаблонов и передачи данных в отображение Class Template { private $template; private $controller; private $layouts; private $vars = array(); function __construct($layouts, $controllerName) { $this->layouts = $layouts; $arr = explode("_", $controllerName); $this->controller = strtolower($arr); } // установка переменных, для отображения function vars($varname, $value) { if (isset($this->vars[$varname]) == true) { trigger_error ("Unable to set var `" . $varname . "`. Already set, and overwrite not allowed.", E_USER_NOTICE); return false; } $this->vars[$varname] = $value; return true; } // отображение function view($name) { $pathLayout = SITE_PATH . "views" . DS . "layouts" . DS . $this->layouts . ".php"; $contentPage = SITE_PATH . "views" . DS . $this->controller . DS . $name . ".php"; if (file_exists($pathLayout) == false) { trigger_error ("Layout `" . $this->layouts . "` does not exist.", E_USER_NOTICE); return false; } if (file_exists($contentPage) == false) { trigger_error ("Template `" . $name . "` does not exist.", E_USER_NOTICE); return false; } foreach ($this->vars as $key => $value) { $$key = $value; } include ($pathLayout); } }

Если вы внимательно прочитали код, то наверняка поняли, что для отображения на страницах у нас используется шаблон first_layouts и вьюха(отображение) index.php – ее код я приводил чуть выше. Все что нам осталось, это создать файл шаблона first_layouts. Расположим его в папке /views/layouts/first_layouts.php
Шаблон будет содержать вот такой код:

header

footer

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

Паттерн Model-View-Controller (MVC) , открытый в в конце 1970-х, представляет собой шаблон проектирования архитектуры программного обеспечения, основной задачей которого является отделение функций работы с данными от их представления. Теоретически, грамотно спроектированное MVC-приложение позволит фронтенд и бэкенд разработчикам в ходе работы не вмешиваться в зоны ответственности друг друга, то есть фронтенд-разработчику не понадобиться что-либо знать о «кухне» своего бэкенд-коллеги и наоборот.

Хотя изначально MVC был спроектирован для разработки десктоп-приложений, он был адаптирован для современных задач и пользуется у веб-разработчиков огромной популярностью, поскольку за счёт разделения ответственности стало возможным создавать более ясный, готовый к повторному использованию код. Паттерн MVC приводит к созданию ясных, модульных систем, что позволяет разработчикам очень быстро вносить изменения в существующий код.

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

Понимание MVC

Как уже было сказано, название паттерна происходит от аббревиатуры трёх слов: Model (модель), View (представление) и Controller (контроллер) . Вкратце принцип работы паттерна можно проиллюстрировать одной схемой ( можно найти на Википедии):

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

Модель

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

Крайне важной чертой модели является то, что технически она не имеет никаких знаний ни о том, что происходит с данными в контроллере и представлении. Модель никогда не должна делать или ожидать каких-либо запросов в/из других компонентов паттерна.

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

Представление

Представление — это то, где данные, полученные от модели, выводятся в нужном виде. В традиционных веб-приложениях, разработанных в рамках MVC-паттерна, представление — это часть системы, где выполняется генерация HTML-кода. Представление также отвечает за получение действий от пользователя с тем чтобы отправить их контроллеру. Например, представление отображает кнопку в пользовательском интерфейсе, а после её нажатия вызывает соответствующее действие контроллера.

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

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

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

Также важным моментом является то, что представление никогда не работает с «чистыми» данными от контроллера, то есть контроллер никогда не работает с представлением в обход модели. В процессе взаимодействия контроллера и представления модель всегда должна находиться между ними.

Контроллер

Контроллер — это последняя часть связки MVC. Задачей контроллера является получение данных от пользователя и манипуляция моделью. Именно контроллер, и только он, является той частью системы, которая взаимодействует с пользователем.

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

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

MVC в PHP

Предлагаю попробовать реализовать описанное выше в небольшом приложении. Начнём с того, что создадим классы модели, представления и контроллера:

string = "MVC + PHP = Awesome!"; } } controller = $controller; $this->

" . $this->model->string . "

"; } } model = $model; } }

Основные классы готовы. Теперь давайте свяжем их вместе и запустим наше приложение:

output();

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

Давайте немного расширим приложение, добавив немного интерактивности, чтобы увидеть, как работает контроллер:

string = “MVC + PHP = Awesome, click here!”; } } controller = $controller; $this->model = $model; } public function output() { return "

model->string . "

"; } } model = $model; } public function clicked() { $this->model->string = “Updated Data, thanks to MVC and PHP!” } }

И в завершение немного модернизируем связующий код:

{$_GET["action"]}(); } echo $view->output();

Итоги

В этой небольшой статье мы рассмотрели основные концепции шаблона проектирования MVC и разработали простенькое приложение на его базе, хотя конечно, нам ещё очень далеко до того, чтобы использовать это в реальной жизни. В следующей статье мы рассмотрим основные затруднения, с которыми вы столкнётесь, если плотнее займётесь построением архитектуры приложения на базе MVC-паттерна. Stay tuned!

Что такое MVC?

Итак, MVC - это про пользовательский интерфейс (UI). Не обязательно графический, голосовое управление тоже годится. Не забудем, что программа может не иметь пользовательского интерфейса, может иметь программный интерфейс (API) или вообще никакого не иметь и всё ещё быть полезной.

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

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

Юзкейсы

В качестве примера представьте терминал для торговли на бирже. Пользователь терминала выставляет заявку, в которой указывает, что он хочет купить акции компании «Светлый путь» в количестве 20 штук по цене 1500 рублей за акцию. Также указывает, что заявка действительна в течение четырёх часов, и с какого из его счетов списать деньги, в случае успешной сделки.

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

Но на бирже нельзя изменить заявку, в предметной области нет такого понятия. Заявку можно только выставить и отменить. Чтобы дать пользователю возможность в один клик менять заявку, надо запоминать старые значения, снимать заявку, давать редактировать то, что запомнили, и выставлять новую заявку. Такая комбинация. Но для пользователя она выглядит как одно простое действие: изменение заявки. Это называется - use case.

Дополним нашу диаграмму местом под юзкейсы.

Ещё пользователю надо дать возможность дёргать эти юзкейсы и получать результат. Это могут быть кнопки и другие графические элементы ввода-вывода, жесты, распознавание и синтез речи. Любой вариант обмена данными и командами. Вуаля:

Пользователь дёргает какой-то из юзкейсов, который, в свою очередь, производит манипуляции над программой. Программа публикует результат или изменения в её состоянии.

Так где же тут все-таки MVC?

Все, что осталось - это только раздать знакомые имена образовавшимся компонентам.

Когда модель публикует изменения, её не волнует для кого, она ничего не знает про View. Вместо или вместе со View на том конце может быть другая подсистема.

Теперь немного частностей.

Это был классический вариант MVC - Active Model. Бывает и так, что модель не оповещает об изменениях. Тогда эту обязанность берёт на себя контроллер. Он знает, какие манипуляции производит над моделью, и, очевидно, знает, какие изменения в состоянии модели могут последовать. Это Passive Model.

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

За материал благодарим нашего подписчика Станислава Ильичева

Фреймворк 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, и прямо сейчас вы можете получить небольшой вводный видеокурс, чтобы получить общее представление о возможностях этого фреймворка:

Понравился материал и хотите отблагодарить?
Просто поделитесь с друзьями и коллегами!


Шаблон проектирования Модель-Представление-Контроллер (MVC) — это шаблон программной архитектуры, построенный на основе сохранения представления данных отдельно от методов, которые взаимодействуют с данными.

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

В этой статье я опишу основные принципы, а также рассмотрю определение схемы построения и простой MVC PHP пример.

Что такое MVC

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


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

Модель

Моделью называют постоянное хранилище данных, используемых во всей структуре. Она должна обеспечивать доступ к данным для их просмотра, отбора или записи. В общей структуре «Модель » является мостом между компонентами «Представление » и «Контроллер ».

При этом «Модель » не имеет никакой связи или информации о том, что происходит с данными, когда они передаются компонентам «Представление » или «Контроллер ». Единственная задача «Модели » — обработка данных в постоянном хранилище, поиск и подготовка данных, передаваемых другим составляющим MVC .

«Модель » должна выступать в качестве «привратника », стоящего возле хранилища данных и не задающего вопросов, но принимающего все поступающие запросы. Зачастую это наиболее сложная часть системы MVC . Компонент «Модель » — это вершина всей структуры, так как без нее невозможна связь между «Контроллером » и «Представлением ».

Представление

Представление — это часть системы, в которой данным, запрашиваемым у «Модели », задается окончательный вид их вывода. В веб-приложениях, созданных на основе MVC , «Представление » — это компонент, в котором генерируется и отображается HTML -код.

Представление также перехватывает действие пользователя, которое затем передается «Контроллеру ». Характерным примером этого является кнопка, генерируемая «Представлением ». Когда пользователь нажимает ее, запускается действие в «Контроллере».

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

«Чтобы правильно применять архитектуру MVC, между «Моделью» и «Представлением» не должно быть никакого взаимодействия: вся логика обрабатывается «Контроллером».

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

Компоненту «Представление » никогда не передаются данные непосредственно «Контроллером ». Между «Представлением » и «Контроллером » нет прямой связи — они соединяются с помощью «Модели ».

Контроллер

Его задача заключается в обработке данных, которые пользователь вводит и обновлении «Модели ». Это единственная часть схемы, для которой необходимо взаимодействие пользователя.

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

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

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

MVC в PHP

Напишем на PHP веб-приложение, архитектура которого основана MVC . Давайте начнем с примера каркаса:

string = "MVC + PHP = Awesome!"; } } controller = $controller; $this->model = $model; } public function output(){ return "

" . $this->model->string . "

"; } } model = $model; } }

У нас есть проект с несколькими основными классами для каждой части шаблона. Теперь нужно настроить взаимосвязь между ними:

output();

В приведенном выше примере PHP MVC нет никакого специфического функционала для контроллера, потому что в приложении не определены взаимодействия пользователя. Представление содержит весь функционал, так как наш пример предназначен лишь для демонстрации.

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

string = “MVC + PHP = Awesome, click here!”; } } controller = $controller; $this->model = $model; } public function output() { return "

model->string . "

"; } } model = $model; } public function clicked() { $this->model->string = “Updated Data, thanks to MVC and PHP!”; } }

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

{$_GET["action"]}(); } echo $view->output();