Від автора: у цьому уроці я хотів би поговорити з Вами про шаблон проектування MVC. Це дуже популярний, а головне корисний шаблон проектування, який передбачає повне розділення логіки скрипта від його подання (дизайну). Ми розберемо його теоретичні основи і як практики переробимо раніше створену CMS з міні курсу, який раніше публікувався у нас на сайті, таким чином, щоб повністю відокремити її логіку від дизайну.
Що таке MVC
Це досить складний шаблон проектування та на мою думку це не скільки шаблон — скільки метод або ідея того, як можна організувати нашу веб-додаток. І ця ідея полягає в тому, що б відокремити логіку програмування від подання (тобто від виводу на екран).
Отже, як випливає з назви MVC складається з трьох компонентів модель (Model) – вид (View) або подання і контролер (controller). Давайте розберемо кожен елемент окремо.
Вид або подання — ця частина відповідає за виведення інформації на екран — це вже дизайнерська частина нашого веб — додатки з мінімальною кількістю логіки. Тобто просто кажучи, цей блок відповідає за зовнішній вигляд нашої програми. Завдання подання зберігати дизайн скрипта.
Контролер — блок, який отримує дані від користувача, обробляє, нормалізує їх, також виконує перевірку правильності введення і передає ці оброблені дані в потрібну модель. Також він приймає дані від моделі, потім вибирає потрібне подання, наповнює його даними і відображає на екрані браузера. Але при цьому, ще раз уточню, контролер не повинен містити в собі ніякої інформації про зовнішньому вигляді веб-додатки. Контролер можна розглянути як сполучна ланка між уявленням і моделлю.
Модель — це основа логіки нашого веб-додатки — вона відповідає за розрахунки, вибірку інформації з бази даних, редагування інформації в БД і т. д. Модель можна представити як бібліотеку різних функцій, що дозволяють реалізовувати функціонал нашої програми. Тобто — це блок, який отримує дані від контролера, далі на основі цих даних робить необхідні перетворення, або знову ж таки вибирає дані з БД або змінює їх, а потім передає результат своєї роботи тому контролеру.
Якщо додаток складне те моделей може бути кілька, наприклад модель для роботи зі статтями та модель для роботи з користувачами. Графічно роботу шаблону MVC можна представити за такою схемою:
Тобто на даній схемі ми з Вами бачимо взаємодія між Моделлю Контролером Поданням і браузером користувача. Зеленими стрілками я позначив запити даних або передачу управління елементу, а сірими стрілками позначено отримання результуючих даних.
Дивіться, коли користувач потрапляє на сторінку, то він здійснює якусь дію, наприклад, надсилає форму. Тобто, виконує запит до контролера, контролер у свою чергу, перевіряє ці дані і передає запит до моделі. Модель наприклад зберігає отримані дані в базі даних і повертає контролеру відповідь про успішність проведеної операції. Потім контролер вибирає, який шаблон відобразити, посилає йому дані і отримує відповідь, яка і направляється в браузер користувача.
По діаграмі видно, що контролер може використовувати кілька різних шаблонів для відображення сторінки скрипта. Далі, як Ви бачите, шаблони безпосередньо не працюють з моделлю, вони можуть отримувати дані лише через контролер. Аналогічно модель не може впливати на шаблони. Тобто контролер виступає сполучною ланкою між моделлю і поданням. Користувачі, в свою чергу, також не можуть безпосередньо працювати з шаблонами і з моделлю, все, що вони бачать — це сторінки надаються контролером.
Правка точки входу на сайт
На мій погляд, найбільш цікаво буде перевести вже готовий робочий проект на структуру MVC, ніж працювати з вигаданим прикладом. Тому в даному уроці ми будемо працювати з простою CMS, яка була створена в міні курсі, що публікувався раніше на нашому сайті. На всяк випадок продублюю посилання на цей міні курс. Ось її вигляд в браузері:
Думаю, Ви прекрасно пам’ятаєте. Дана CMS досить непогана і прекрасно виконує свої завдання. Але у неї є один суттєвий недолік. В її коді перемішана логіка з зовнішнім виглядом. А це не дуже добре з точки зору доступності коду, так і надалі, дуже важко буде щось змінити в коді, особливо якщо це стосується дизайну. Так як не вийде змінити дизайн не зачіпаючи логіку роботи даної CMS.
Тому в даному уроці ми переробимо частина даної CMS на структуру шаблону MVC і якщо ця ідея Вам сподобається, то решту Ви доробите самостійно. Отже, першим ділом змінимо головний файл даній CMS index.php:
get_body($class);
}
exit(“
Немає даних для входу
“);
}
?>
Зверніть увагу – я прибрав ручне підключення необхідних файлів з класами і додав функцію __autoload() – функція автоматичного завантаження класів. Яка буде виконувати підключення відсутніх файлів з класами. І прибрав перевірку наявності файлу, перед створенням його об’єкта. Так як це виконується в опції __autoload(). Так і папку classes я перейменував в controller (у ній міститимуться контролери). Також створив дві порожні папки: model і tpl, для зберігання моделі і шаблонів відповідно.
Створення моделі
Якщо ми подивимося, наприклад, на файл ACore.php ми побачимо, що в його методах дуже багато коду, який надсилає запити до бази даних. Нам необхідно весь даний код, перенести в модель. При цьому в моделі необхідно створити окремі методи, які будуть повертати масиви даних подученних з бази даних. Тому в папці model створюємо файл з наступним вмістом:
db = mysql_connect(HOST,USER,PASSWORD);
if(!$this->db) {
exit(“Помилка з’єднання з базою даних”.mysql_error());
}
if(!mysql_select_db(DB,$this->db)) {
exit(“Немає такої бази даних”.mysql_error());
}
mysql_query(“SET NAMES ‘UTF8′”);
}
public function get_left_bar(){
$query = “SELECT id_category,name_category FROM category”;
$result = mysql_query($query);
if(!$result) {
exit(mysql_error());
}
for($i = 0;$i < mysql_num_rows($result); $i++) {
$row[] = mysql_fetch_array($result, MYSQL_ASSOC);
}
return $row;
}
public function menu_array() {
$query = “SELECT id_menu,name_menu FROM menu”;
$result = mysql_query($query);
if(!$result) {
exit(mysql_error());
}
$row = array();
for($i = 0;$i < mysql_num_rows($result); $i++) {
$row[] = mysql_fetch_array($result, MYSQL_ASSOC);
}
return $row;
}
public function get_main_content() {
$query = “SELECT id,title,discription,date,img_src FROM statti ORDER BY date DESC”;
$result = mysql_query($query);
if(!$result) {
exit(mysql_error());
}
for($i = 0; $i < mysql_num_rows($result);$i++) {
$row[] = mysql_fetch_array($result,MYSQL_ASSOC);
}
return $row;
}
public function get_cat($id_cat) {
$query = “SELECT id,title,discription,date,img_src
FROM statti
WHERE cat=’$id_cat’
ORDER BY date DESC”;
$result = mysql_query($query);
if(!$result) {
exit(mysql_error());
}
$row = array();
for($i = 0; $i
Думаю, Ви побачите тут знайомі рядки коду. Так як вони просто скопійовані з класів ACore, main, category і menu.
Редагуємо ядро – клас ACore
Весь зайвий код ми з нього прибрали (перенесли в модель, залишилися тільки фрагменти дизайну. Який, нам потрібно обов’язково виключити та перенести в окремий шаблон. Ось виправлений код ACore.php:
m = new model();;
}
protected function get_header() {
return TRUE;
}
protected function get_left_bar() {
$result = $this->m->get_left_bar();
return $result;
}
protected function get_menu() {
$row = $this->m->menu_array();
return $row;
}
protected function get_footer() {
$row = $this->m->menu_array();
return $row;
}
public function get_body($tpl) {
if($_POST || $_GET[‘delete’]) {
$this->obr();
}
$this->get_header();
$left_bar = $this->get_left_bar();
$menu_top = $this->get_menu();
$content = $this->get_content();
$footer = $this->get_footer();
//підключення шаблону
include “tpl/index.php”;
}
abstract function get_content();
}
?>
Зверніть увагу, який вид придбав клас ACore – погодьтеся такий код набагато зручніше читати і редагувати.
Так хочу звернути увагу на метод get_body(). Всі методи, які викликаються в ньому – повинні повертати дані. Які, надалі, зберігаються в змінної. Це потрібно для того що б вивести дані в шаблонах. Так як в кінці даного методу ми підключаємо головний файл шаблону. А значить у файлах, що підключаються, будуть доступні змінні з даними, що повернуть методи get_header(), get_left_bar(), get_menu() і т. д.
Так само зверніть увагу, що метод get_body(). Тепер повинен приймати параметр $tpl – це ім’я завантажуваного класу (поточного контролера). Цей параметр буде передаватися з файлу index.php. І він необхідно для формування динамічних вкладених шаблонів. Всі шаблони збережені в окремих файлах з однойменними іменами з контролерами.
Редагування класів: main, menu і category
Аналогічним чином змінюємо код контролерів main, menu і category. Файл main.php:
m->get_main_content();
return $result;
}
}
?>
Файл menu.php:
m->get_menu($id_menu);
return $row;
}
}
}
}
?>
Файл category.php:
m->get_cat($id_cat);
return $result;
}
}
}
}
?>
Як Ви бачите ніяких запитів до бази даних і коду зовнішнього вигляду.
Створення шаблонів
Шаблони – це файли з кодом, які відповідають за зовнішній вигляд скрипта. Весь код наступних файлів узятий з початкового CMS, тобто з трьох контролерів main, menu і категорії та класу ACore (просте копіювання HTML коду). Отже, головний файл шаблону, який збирає в єдине ціле всі частини шаблону:
Зверніть увагу центральна частина – це динамічна частина та шаблон формується за допомогою змінної $tpl – тобто це ім’я завантаженого в даний момент контролера. Файл шапки залишається без змін – його просто копіюємо в папку tpl (header.php). Всі файли шаблону містяться в папці tpl! Шаблон лівої колонки (файл left_bar.php):
Шаблон верхнього горизонтального меню (файл menu_top.php):
Шаблон футера (файл footer.php):
І три динамічних шаблону. Шаблон головної сторінки main.php):