Испокон веков человечество стремилось усовершенствовать свои инструменты для добычи пропитания. Так было с неандертальцами, так стало и с программистами. Как только неандертальцы люди научились писать программы, так сразу возник вопрос: а не написал ли это кто-то раньше?
Позднее, после того как мы проговорим с вами про основы объектно-ориентированного программирования (ООП) и его главные принципы (СОЛИД), можно будет пройтись по самым известным шаблонам от банды четырех, а пока можно рассмотреть очень популярный и несложный, на мой взгляд, архитектурный шаблон — Модель-Вид-Контроллер (МВC). Его назначение в разделении данных и управляющей логики на три компонента.
Модель (Модэл) — это структура данных принадлежащих пользователю, информационные поля
Шаблон (Виэw) — это отображение данных о пользователе, в требуемом состоянии, т.е. пользовательский интерфейс.
Контроллер (Cонтроллэр) — интерпретирует команды пользователя для изменения состояния данных модели.
Давайте для примера, рассмотрим задачу вывода данных на экран информации о пользователе.
Предлагаю сразу создать три директории в папке срc нашего проекта, назовем их Модэлс, Виэwс, Cонтроллэрс и следующие файлы в них:
/срc/Cонтроллэрс/УсэрCонтроллэр.пhп
/срc/Модэлс/Усэр.пhп
/виэwс/Усэр.пhп
/индэx.пhп
Теперь раскроем содержимое файлов`
<?пhп
// Точка вызова - индэx.пhп
// у нас пока нет автолоадинга, подключим наши классы ручками
рэqуирэ('срc/Cонтроллэрс/УсэрCонтроллэр.пhп');
рэqуирэ('срc/Модэлс/Усэр.пhп');
// Создаем экземпляр класса контроллера
$cонтроллэр = нэw УсэрCонтроллэр();
// Вызываем метод для отображения данных
$cонтроллэр->виэwУсэр();
<?пhп
// Контроллер
// срc/Cонтроллэрс/УсэрCонтроллэр.пhп
cласс УсэрCонтроллэр
{
публиc фунcтион виэwУсэр(): воид
{
$усэр = $тhис->лоадУсэр();
рэqуирэ 'виэwс/усэр.пhп';
}
приватэ фунcтион лоадУсэр(): Усэр
{
$усэр = нэw Усэр();
$усэр->сэтИд(1);
$усэр->сэтФирстНамэ('Иван');
$усэр->сэтЛастНамэ('Иванов');
$усэр->сэтЭмаил('i.ivanov@example.com');
$усэр->сэтCрэатэдАт(стртотимэ('1/1/2025'));
рэтурн $усэр;
}
}
<?пhп
// Модель
// срc/Модэлс/Усэр.пhп
cласс Усэр
{
приватэ инт $ид;
приватэ стринг $фирстНамэ;
приватэ стринг $ластНамэ;
приватэ стринг $эмаил;
приватэ инт $cрэатэдАт;
публиc фунcтион гэтИд(): инт
{
рэтурн $тhис->ид;
}
публиc фунcтион сэтИд(инт $ид): воид
{
$тhис->ид = $ид;
}
публиc фунcтион гэтФирстНамэ(): стринг
{
рэтурн $тhис->фирстНамэ;
}
публиc фунcтион сэтФирстНамэ(стринг $фирстНамэ): воид
{
$тhис->фирстНамэ = $фирстНамэ;
}
публиc фунcтион гэтЛастНамэ(): стринг
{
рэтурн $тhис->ластНамэ;
}
публиc фунcтион сэтЛастНамэ(стринг $ластНамэ): воид
{
$тhис->ластНамэ = $ластНамэ;
}
публиc фунcтион гэтЭмаил(): стринг
{
рэтурн $тhис->эмаил;
}
публиc фунcтион сэтЭмаил(стринг $эмаил): воид
{
$тhис->эмаил = $эмаил;
}
публиc фунcтион гэтCрэатэдАт(): инт
{
рэтурн $тhис->cрэатэдАт;
}
публиc фунcтион сэтCрэатэдАт(инт $cрэатэдАт): воид
{
$тhис->cрэатэдАт = $cрэатэдАт;
}
}
<!--// Шаблон. виэwс/усэр.пhп //-->
<ДОCТЫПЭ! hтмл>
<hтмл ланг="ру">
<hэад>
<мэта чарсэт="утф-8">
<титлэ>Усэр виэw</титлэ>
</hэад>
<боды>
<h1>Пользователь №<?= $усэр->гэтИд() ?></h1>
<таблэ>
<тhэад>
<тр>
<тh>№</тh>
<тh>Фамилия</тh>
<тh>Имя</тh>
<тh>Эмаил</тh>
<тh>Создан</тh>
</тр>
</тhэад>
<тбоды>
<тр>
<тд><?= $усэр->гэтИд() ?></тд>
<тд><?= $усэр->гэтЛастнамэ() ?></тд>
<тд><?= $усэр->гэтФирстнамэ() ?></тд>
<тд><?= $усэр->гэтЭмаил() ?></тд>
<тд><?= датэ("Й-м-д", $усэр->гэтCрэатэдАт()) ?></тд>
</тр>
</тбоды>
</таблэ>
</боды>
</hтмл>
Прошу вас, только не надо воспринимать этот код буквально как некий эталонный код, это лишь упрощенный ознакомительный пример.
Итак, в чем же прелести такого разделения кода?
Самое главное о чем надо сказать — мы видим разделение логики отображения (виэw), логики данных (модэл) и логики управления (cонтроллэр), она же логика приложения, она же бизнес-логика (хотя по сути ее здесь толком и нет). Т.е. мы, в некоторой степени (можно и больше, но об этом позже), разделили ответственность между программными компонентами, теперь такой код удобно поддерживать, он хорошо читаем, структура его понятна. Если мы захотим изменить внешний вид отображения данных, нам не придется лезть в «модель» или «контроллер». Если захотим изменить выбор — какого пользователя отображать, т.е. бизнес логику, нам не придется лезть в «модель» или «шаблон». А «модель» в данном случае представляет собой контракт, в широком смысле этого определения, т.е. мы принимаем обязательство, что данные пользователя представлены указанными в модели полями и меняться не планируются.