Шаблон проектування MVC

79

Від автора: у цьому уроці я хотів би поговорити з Вами про шаблон проектування MVC. Це дуже популярний, а головне корисний шаблон проектування, який передбачає повне розділення логіки скрипта від його подання (дизайну). Ми розберемо його теоретичні основи і як практики переробимо раніше створену CMS з міні курсу, який раніше публікувався у нас на сайті, таким чином, щоб повністю відокремити її логіку від дизайну.

Шаблон проектування MVCШаблон проектування MVC

Що таке MVC

Це досить складний шаблон проектування та на мою думку це не скільки шаблон — скільки метод або ідея того, як можна організувати нашу веб-додаток. І ця ідея полягає в тому, що б відокремити логіку програмування від подання (тобто від виводу на екран).

Отже, як випливає з назви MVC складається з трьох компонентів модель (Model) – вид (View) або подання і контролер (controller). Давайте розберемо кожен елемент окремо.

Вид або подання — ця частина відповідає за виведення інформації на екран — це вже дизайнерська частина нашого веб — додатки з мінімальною кількістю логіки. Тобто просто кажучи, цей блок відповідає за зовнішній вигляд нашої програми. Завдання подання зберігати дизайн скрипта.

Контролер — блок, який отримує дані від користувача, обробляє, нормалізує їх, також виконує перевірку правильності введення і передає ці оброблені дані в потрібну модель. Також він приймає дані від моделі, потім вибирає потрібне подання, наповнює його даними і відображає на екрані браузера. Але при цьому, ще раз уточню, контролер не повинен містити в собі ніякої інформації про зовнішньому вигляді веб-додатки. Контролер можна розглянути як сполучна ланка між уявленням і моделлю.

Модель — це основа логіки нашого веб-додатки — вона відповідає за розрахунки, вибірку інформації з бази даних, редагування інформації в БД і т. д. Модель можна представити як бібліотеку різних функцій, що дозволяють реалізовувати функціонал нашої програми. Тобто — це блок, який отримує дані від контролера, далі на основі цих даних робить необхідні перетворення, або знову ж таки вибирає дані з БД або змінює їх, а потім передає результат своєї роботи тому контролеру.

Якщо додаток складне те моделей може бути кілька, наприклад модель для роботи зі статтями та модель для роботи з користувачами. Графічно роботу шаблону MVC можна представити за такою схемою:

Шаблон проектування MVC

Тобто на даній схемі ми з Вами бачимо взаємодія між Моделлю Контролером Поданням і браузером користувача. Зеленими стрілками я позначив запити даних або передачу управління елементу, а сірими стрілками позначено отримання результуючих даних.

Дивіться, коли користувач потрапляє на сторінку, то він здійснює якусь дію, наприклад, надсилає форму. Тобто, виконує запит до контролера, контролер у свою чергу, перевіряє ці дані і передає запит до моделі. Модель наприклад зберігає отримані дані в базі даних і повертає контролеру відповідь про успішність проведеної операції. Потім контролер вибирає, який шаблон відобразити, посилає йому дані і отримує відповідь, яка і направляється в браузер користувача.

По діаграмі видно, що контролер може використовувати кілька різних шаблонів для відображення сторінки скрипта. Далі, як Ви бачите, шаблони безпосередньо не працюють з моделлю, вони можуть отримувати дані лише через контролер. Аналогічно модель не може впливати на шаблони. Тобто контролер виступає сполучною ланкою між моделлю і поданням. Користувачі, в свою чергу, також не можуть безпосередньо працювати з шаблонами і з моделлю, все, що вони бачать — це сторінки надаються контролером.

Правка точки входу на сайт

На мій погляд, найбільш цікаво буде перевести вже готовий робочий проект на структуру MVC, ніж працювати з вигаданим прикладом. Тому в даному уроці ми будемо працювати з простою CMS, яка була створена в міні курсі, що публікувався раніше на нашому сайті. На всяк випадок продублюю посилання на цей міні курс. Ось її вигляд в браузері:

Шаблон проектування MVC

Думаю, Ви прекрасно пам’ятаєте. Дана 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