Модель MVC и ООП в веб-программировании
MVC (Model, View, Controller) – шаблон проектирования проектов. Он был разработан задолго до появления WWW, но широкое распространение получил именно в веб-разработке. Адаптировавшись под потребности разработчиков, и став основой многочисленному количеству фреймворков, данный шаблон стал очень популярным и востребованным среди веб-разработчиков [17].
Основной идеей MVC является чёткое разделение функционирования приложения (рис. 4).
Рис. 4. Компоненты MVC
Контроллеры обрабатывают запросы от пользователя, будь то обычный GET-запрос, отправка формы, AJAX-запрос и т. д. При получении каких-либо данных, например, параметр в url, задача контроллера – вызвать модель, если необходимо отправить определённые данные от пользователя в методы модели, получить результат и вернуть его на вывод (отобразить вид) в требуемом формате (JSON, HTML, XML и т. д.) Как правило, внутри контроллера не должно быть кода, связанного с непосредственной работой с БД, сложных вычислений, обработки данных и т. д. Распространённой ошибкой разработчиков является то, что бизнес-логика описывается внутри контроллеров, а на модель возлагается только работа с базой данных, из-за чего объём кода контроллеров сильно засоряется и становится сложно читаемым. А так же нарушается основная идея MVC – разделение функциональности. Единственная задача контроллера – получить данные от пользователя, отправить в модель, получить результат и отправить его на вывод.
Модель реализует логику работы приложения – описание сущностей, конфигурацию приложения, подключение к БД, выборки, валидацию, механизмы защиты данных, взаимодействие с внешними сервисами, обработка ошибок и т. д. Основная задача модели – сформировать данные для отправки их в контроллер, а также работа с полученными данными, т. е. реализация бизнес-логики приложения.
Вид получает данные от контроллера и выводит их пользователю в необходимом формате. Как правило таковым является HTML-код, который отображается браузером, но также это может быть JSON-массив (в ответ на AJAX-запрос), сформированный PDF, XML, DOC и т. д. Единственная задача вида – отобрать данные.
В связи со спецификой модели MVC, а именно – чёткого разделения функционирования приложения, при разработке приложений, в том числе в основе многих фреймворков, используется объектно-ориентированное программирование [18]. Основой данного подхода служит единая точка входа, как правило файл index.php (зависит от настроек сервера и файла .htaccess), расположенный в корне сайта, и определённый внутри него автозагрузчик классов. Любой запрос к сайту должен быть перенаправлен именно к этому файлу.
<?
function __autoload($className)
{
$className = ltrim($className, '\\');
$fileName = '';
if ($lastNamespacePos = strrpos($className, '\\')) {
$namespace = substr($className, 0, $lastNsPos);
$className = substr($className, $ lastNamespacePos + 1);
$fileName = str_replace('\\', '/', $namespace) . '/';
}
$fileName = $_SERVER['DOCUMENT_ROOT'].'/'.strtolower($fileName).$className.'.php';
if (file_exists($fileName)) {
require_once($fileName);
} else {
die('Класс ' . $className . ' не найден');
}
}
Листинг 1. Пример простейшего автозагрузчика классов
При вызове в любом участке кода какого-либо класса функция __autoload, указанная в листинге 1, пытается подключить файл с соответствующим именем с учётом пространства имён. В случае отсутствия такового выполнение скрипта прекращается. Это обеспечивает подключение только необходимых в процессе выполнения скрипта файлов.
Следующей неотъемлемой частью данного подхода является роутер. Он обрабатывает входную url-строку и определяет какой метод класса-контроллера должен быть вызван. В общем случае каждой url-строке ставится в соответствие определённый метод класса-контроллера. В случае, если соответствие не установлено, отображается страница 404.
Класс-контроллер представляет собой набор методов, задача которых получить входные данные, обработать их с помощью методов классов-моделей и возвратить ответ, который будет выведен пользователю. В приложении таковых классов может быть множество, они могут наследоваться от базового абстрактного класса-контроллера, содержать вспомогательные методы, которые не вызываются роутером. Но основная их задача, в соответствии с MVC – содержать методы, которые получают входные данные от пользователя и возвращают ему результат обработки.
Классы модели описывают бизнес-логику приложения. Они могут содержать описание сущностей базы данных, сложные вычисления, методы для взаимодействия с различными внешними сервисами, обработчики событий и т. д. Каждый класс-модель содержит свойства и методы, объединённые общей логикой и предназначением. Экземпляры данных классов могут быть использованы как в контроллерах, так и в других классах модели.
Вид, в контексте ООП в простейшем случае представляет собой php-шаблоны, содержащие вёрстку и наполняемые данными, пришедшими от контроллера. В более сложных проектах в качестве шаблонов используются специальные библиотеки, предоставляющие механизм наследование шаблонов, переопределения отдельных блоков, специальный упрощённый синтаксис для вывода данных, встроенное кэширование.