Принцип роботи диспетчера в OpenCart

310

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

Почнемо ми з з’ясування, що ж таке процес диспетчеризації, і поступово перейдемо до розбору шматків коду з різних частин фреймворка.

В статті я буду працювати з останньою версією OpenCart, проте весь процес в більшій своїй частині не відрізняється від попередніх версій.

Коротко про диспетчеризації

У веб-додатках процес диспетчеризації відповідає за пошук відповідності вхідного запиту URL і відповідного модуля у фреймворку. Реалізація даного процесу в різних фреймворках виконана по-різному, але основна концепція скрізь одна і та ж. Завдання, які виконує диспетчер:

Витягує з запитуваного об’єкта відповідні параметри.

Принцип роботи диспетчера в OpenCart

Інтернет-магазин на OpenCart!

Створити інтернет-магазин на самій популярної CMS OpenCart з нуля!

Приступити до створення

Знаходить відповідний модуль і дія на виконання.

Якщо модуль і дія знайдені, диспетчер припиняє свою роботу.

Якщо за запитом модуль не знайдений, встановлюється за замовчуванням, і диспетчер припиняє роботу.

Спробуємо розібратися у вищесказаному на простому прикладі OpenCart. Для створення нового користувача з боку front-end’а, необхідно зареєструвати його на сайті за допомогою адреси http://www.youropencartstore.com/index.php?route=account/register. Розпишемо поетапно процес рендеринга запитаної сторінки в OpenCart.

Перше, перевіряється, чи є в адресному рядку мінлива route. Якщо її немає, то для змінної route встановлюється значення за замовчуванням «common/home».

У нашому випадку змінна є, а значить, будуть задані потрібні змінні і запуститься процес диспетчеризації.

Першим етапом будуть запущені так звані дії «preAction», виконують стандартні завдання. Більш детально про preAction’ах ми поговоримо в останній частині статті.

В кінці перевіряється, чи існує файл контролера для поточної змінної route. Якщо файл є, він буде викликаний для отримання відповіді.

Якщо потрібної змінної route немає файлу контролера, буде виконано дію «error/not_found». У користувача висвітиться повідомлення «page not found».

Це поверхневий погляд на те, як OpenCart розбирає запитаний URL адресу і повертає відповідь. В наступній секції ми більш детально розглянемо цей процес.

Докладний розбір процесу диспетчеризації

В корені каталогу OpenCart знайдіть і відкрийте файл index.php. У цьому файлі багато чого відбувається, але не лякайтеся, здебільшого там просто задаються об’єкти, які потім використовуються у фреймворку. Відразу ж розберемо зацікавив нас шматок коду.

// Front Controller
$controller = new Front($registry);
// Maintenance Mode
$controller->addPreAction(new Action(‘common/maintenance’));
// SEO url’s
$controller->addPreAction(new Action(‘common/seo_url’));

Як і більшість інших фреймворків, OpenCart працює за шаблоном front-controller – для всіх запитів у програмі існує єдина точка входу, один контролер обробляє всі запити.

Перше, що робить, це створюємо новий примірник єдиного контролера і записуємо його в змінну $controller. Наступним рядком ми викликаємо метод addPreAction і додаємо кілька дій.

Тепер виникає інше питання: що таке preAction? Простими словами, preAction – дія, що виконується до потрібної дії на будь-якій сторінці. Наприклад, коли користувач клікає на будь-яку сторінку, перед поверненням відповіді вам потрібно перевірити, а чи не знаходиться сайт в режимі обслуговування. У такому випадку можна використовувати preAction, і якщо сайт знаходиться в режимі обслуговування, користувача перекине а сторінку зі спеціальним повідомленням.

Принцип роботи диспетчера в OpenCart

Інтернет-магазин на OpenCart!

Створити інтернет-магазин на самій популярної CMS OpenCart з нуля!

Приступити до створення

Ми додали preAction common/seo_url, так як якщо на сайті активовані SEO адреси, то нам потрібно витягнути відповідні змінні route ще до старту процесу диспетчеризації. Перейдемо до наступного важливого шматка коду.

// Router
if (isset($request->get[‘route’])) {
$action = new Action($request->get[‘route’]);
} else {
$action = new Action(‘common/home’);
}

Тут перевіряється наявність в рядку запиту змінної route. Якщо вона є, то ми передаємо поточне значення змінної route аргумент конструктора створюємо об’єкт класу Action. Якщо змінної немає, ми робимо те ж саме, але вже з домашньою сторінкою — common/home. Задавши значення змінної $action, можна переходити далі.

// Dispatch
$controller->dispatch($action, new Action(‘error/not_found’));

І нарешті, ми викликаємо метод dispatch класу контролера. Відкрийте файл system/engine/front.php і знайдіть рядки.

public function dispatch($action, $error) {
$this->error = $error;
foreach ($this->pre_action as $pre_action) {
$result = $this->execute($pre_action);
if ($result) {
$action = $result;
break;
}
}
while ($action) {
$action = $this->execute($action);
}
}

У цьому методі і відбувається вся магія! Спочатку виконуються всі описані вище preAction’и. Далі в циклі while я намагаюся виконати наш поточний $action, який передається як аргумент методу execute. Знайдемо оголошення методу execute в цьому ж файлі.

private function execute($action) {
$result = $action->execute($this->registry);
if (is_object($result)) {
$action = $result;
} elseif ($result === false) {
$action = $this->error;
$this->error = “;
} else {
$action = false;
}
return $action;
}

У першій рядку викликається метод execute класу Action. Не плутайте його з методом execute класу Front controller. Відкрийте файл system/engine/action.php і знайдіть:

public function execute($registry) {
// Зупиняємо всі викликані методи
if (substr($this->method, 0, 2) == ‘__’) {
return false;
}
if (is_file($this->file)) {
include_once($this->file);
$class = $this->class;
$controller = new $class($registry);
if (is_callable(array($controller, $this->method))) {
return call_user_func(array($controller, $this->method), $this->args);
} else {
return false;
}
} else {
return false;
}
}

Тут важливо помітити, коли об’єкт дії створюється у файлі index.php у конструкторі класу Action вже задаються всі потрібні змінні. Конкретно, задаються властивості file, class і method, які потім використовуються в методі execute. Щоб не ускладнювати, ми розберемо тільки метод execute. Але я б порадив вам самим розібратися з конструктором класу Action.

Повертаючись до нашого методу execute класу Action, він перевіряє, чи є файл ($this->file), що відноситься до поточного значення змінної route. Якщо все нормально, файл підключається, і з допомогою функції call_user_func викликається відповідний метод ($this->method) класу контролера і повертається відповідь.

Якщо файлу не існує, повертається false. Повернемося до коду методу execute класу Front controller. Потерпіть, залишилося трохи!


$result = $action->execute($this->registry);
if (is_object($result)) {
$action = $result;
} elseif ($result === false) {
$action = $this->error;
$this->error = “;
} else {
$action = false;
}
return $action;

Після виконання методу execute класу Action отриманий результат записується в змінну $result. У змінній $result може зберігатися 3 можливих результату. Розберемо кожний з них.

Якщо все пройшло нормально, в змінній $result буде знаходитися HTML-код, змінна $action задається в false, і процес диспетчеризації закінчується. Це випадок, коли за кодом ми потрапили в останній блок else.

Згадайте, якщо відповідний файл контролера не знайдений в методі execute класу Action, то ми повертали false. В такому випадку змінної $action буде присвоєно значення $this->error (дію error/not_found), а користувачеві покажуть повідомлення «page not found».

І останнє, якщо змінна $result є об’єктом, то ми записуємо даний об’єкт в змінну $action. Звучить дивно: навіщо методом контролера повертати інший об’єкт Action, якщо він повинен повернути HTML код потрібної сторінки? Це просто один із способів контролера по редіректу користувачів на інший URL.

Давайте відкриємо файл catalog/controller/common/maintenance.php і швиденько пробіжимося по ньому. При дотриманні певних умов у методі index повертається об’єкт Action.


if (($route != ‘payment’ && $route != ‘api’) && !$this->user->isLogged()) {
return new Action(‘common/maintenance/info’);
}

З коду зрозуміло, що метод повертає об’єкт Action для того, щоб перенаправити користувача на сторінку common/maintenance/info. У методі dispatch класу Front Controller є код, який обробляє дане перенаправлення. Згадайте код з того методу – обіцяю, що це останній шматок коду в цьому уроці.


while ($action) {
$action = $this->execute($action);
}

Це циклу while, який крутиться до тих поки, поки $action не буде дорівнює false! Більш зрозумілою мовою, цикл припиниться, як тільки у нас буде, що показати користувачеві. Ось і кінець. Сподіваюся, що урок був не так складний, як могло здатися на перший погляд.

Висновок

Сьогодні ми розглянули важливий процес у фреймворку OpenCart – процес диспетчеризації. Ми розібралися з основними моментами і пройшли по всьому циклу диспетчеризації, щоб зрозуміти принцип його роботи.

Принцип роботи диспетчера в OpenCart

Інтернет-магазин на OpenCart!

Створити інтернет-магазин на самій популярної CMS OpenCart з нуля!

Приступити до створення