Несмотря на то, что MVC известен практически каждому веб-разработчику, его использование в реальных проектах часто вызывает затруднения. Главная идея MVC — повторное использование кода и разделение проблем. В данном разделе будут описаны общие принципы, которые помогут следовать MVC в вашем приложении.
Предположим, что веб-приложение состоит из нескольких подприложений, таких как
Подприложения могут быть реализованы в виде модулей или как приложение, которое содержит код, общий для нескольких подприложений.
Модели представляют структуру данных, которая
используется в приложении, и часто являются общими для нескольких подприложений.
К примеру, модель LoginForm может быть использована как в пользовательской, так
и в административной части приложения. Модель News может использоваться
консольными командами, API и front/back частями приложения. Поэтому, модели
должны содержать свойства, представляющие конкретные данные;
должны включать в себя бизнес-логику (например, правила валидации) для того, чтобы убедиться, что данные соответствуют требованиям;
могут содержать код для работы с данными. К примеру, модель SearchForm,
помимо данных для поиска, может содержать метод search, который этот поиск
производит.
Иногда следование последнему перечисленному правилу делает модель очень
толстой, то есть содержащей очень много кода в одном классе. Это может привести
к трудностям поддержки кода в том случае, если модель используется несколькими
способами. К примеру, модель News может содержать метод getLatestNews,
который используется только пользовательской частью и метод getDeletedNews,
который используется только административной частью. Для небольших и средних
приложений это допустимо. Для крупных же приложений в целях улучшения
поддерживаемости кода можно сделать следующее:
Создать модель NewsBase, содержащую только код, общий для подприложений
(пользовательской и административной частей);
В каждом подприложении создать модель News, наследуемую от NewsBase и
определить в ней специфичные для подприложения методы.
Таким образом, если применить это к рассмотренному выше примеру, необходимо
добавить модель News с методом getLatestNews в пользовательскую часть и
ещё одну модель News с методом getDeletedNews в административную часть.
В общем случае модели не должны напрямую взаимодействовать с пользователем. То есть:
не должны использовать $_GET, $_POST или другие подобные переменные, напрямую
получаемые из запроса пользователя так как модели могут использоваться в
совершенно других подприложениях (например, в модульных тестах или API), в
которых эти переменные недоступны. Все переменные, относящиеся к запросу
пользователя, должны обрабатываться в контроллере;
не должны генерировать HTML или другой код представления, так как он может изменяться в зависимости от нужд пользователя (то есть, пользовательская часть и административная часть могут показывать новости в совершенно разном формате). Такой код должен обрабатываться в представлениях.
Представления отвечают за представление моделей в нужном пользователю формате. В общем случае представления
должны, главным образом, содержать разметку, такую как HTML, и простой PHP код, используемый для обхода, форматирования и отображения данных;
не должны напрямую обращаться к базе данных. Этим должны заниматься модели;
не должны напрямую обращаться к $_GET, $_POST и другим переменным, получаемым
из запроса пользователя. Эту задачу должен выполнять контроллер. Представление
же должно использоваться для задания внешнего вида данных, полученных из
контроллера и модели;
может напрямую обращаться к свойствам и методам контроллера или моделей. При этом данные свойства и методы должны отвечать за отображение.
Представления можно использовать повторно несколькими способами:
Общий шаблон: в него можно вынести разметку, общую для всех страниц. Например, шапку и подвал;
Части шаблона: используются внутри других шаблонов и, как правило, не
используются с общим шаблоном. К примеру, часть шаблона _form.php можно
использовать для отображения формы ввода модели, которая будет использоваться
как при её создании, так и при редактировании;
Виджеты: используются в том случае, когда для части шаблона требуется слишком много логики. При этом логика переносится в класс виджета. Виджет, генерирующий большое количество разметки, может использовать свои шаблоны представлений;
Хелперы: в шаблонах часто требуется выполнять небольшие задачи, такие как форматирование данных или генерация HTML-тегов. Вместо того, чтобы вставлять код напрямую в шаблоны, можно поместить его в класс-хелпер и использовать в шаблонах этот класс. Пример такого подхода можно найти в классе CHtml, который помогает генерировать часто используемый HTML код. Для того, чтобы избежать явного подключения классов, хелперы можно положить в отдельную директорию, прописанную в import.
Контроллеры — связующее звено, соединяющее модели, представления и другие компоненты в рабочее приложение. Контроллер отвечает за обработку запросов пользователя. Поэтому контроллер
может обращаться к $_GET, $_POST и другим переменным PHP, получаемым из
запроса пользователя;
может создавать экземпляры моделей и управлять ими. К примеру, в типичном действии
обновления модели контроллер может сначала создать экземпляр модели, затем
заполнить его данными из $_POST и, после успешного сохранения модели, перенаправить
браузер пользователя на страницу созданной модели. Стоит отметить, что само сохранение
модели должно быть реализовано в модели, а не в контроллере;
не должен содержать SQL-запросов. Их лучше держать в моделях;
не должен содержать HTML и другой разметки. Её стоит вынести в представления.
В хорошо спроектированном MVC-приложении контроллеры обычно очень тонкие и содержат только несколько десятков строк кода. В то же время, модели очень толстые и содержат большую часть кода, связанную с обработкой данных, так как структура данных и бизнес-логика, содержащиеся там, обычно довольно специфичны для конкретного приложения. Логика контроллера, наоборот, довольно типична и может быть вынесена в базовые классы.
Be the first person to leave a comment
Please login to leave your comment.