Magento для PHP MVC розробників – розбір Контролера (ч.2/11)
Архітектура Model-View-Controller (MVC) бере своє походження від мови програмування Smalltalk і Xerox Parc. З тих пір з’явилось багато нових систем, які описують свою архітектуру як MVC. Кожна система різниться, але всі вони ставлять своєю ціллю розділення доступу до даних, бізнес-логіки та інтерфейсу.
Архітектура більшості PHP MVC фреймворків буде виглядати приблизно так:
- URL перехоплюється особливим PHP файлом (зазвичай називається Front Controller)
- Цей PHP-файл проаналізує URL, отримає ім’я контролера та ім’я дії (Action): цей процес часто називається маршрутизацією (routing)
- Отриманий контролер буде в якості нового екземпляра
- Отримана назва методу порівнюється з отриманим ім’ям дії (Action), що викликається в контролері
- Цей екшен характеризує і викликає методи моделей, залежних від змінних запиту (request)
- Метод Екшену (Action) також підготує структуру даних інформації, котра буде передана View
- View потім генерує HTML, використовуючи інформацію в структурі даних, отриману від контролера.
У той час, як дана модель є великим кроком вперед (від патерну “кожен файл є сторінкою”, що був на початку), для деяких програмістів це все ще здається “необтесаним”. Загальними претензіями до подібної моделі є:
- PHP-файл Front Controller’а досі оперує в глобальному просторі імен
- Збірка над конфігурацією призводить до меншої модульності
- URL-адреси маршрутизації часто не гнучкі
- Контролери часто прив’язані до конкретних Views
- Навіть тоді, коли система пропонує спосіб перевизначення базових значень (defaults), збірка призводить до застосунків, в яких стає важко/неможливо відмовлятися від накопичення все нових моделей, або реалізацій контролера без масивного рефакторингу.
Як ви, напевно, здогадалися, команда Magento поширює цей світогляд і створила більш абстрактний MVC-шаблон, котрий виглядає приблизно так:
- URL перехоплюється в окремому PHP файлі
- Цей PHP-файл створює екземпляр аплікації Magento
- Аплікація Magento створює екземпляр об’єкту Front Controller
- Front Controller створює екземпляри будь-якої кількості маршрутів (Router), вказаних в глобальній конфігурації
- Маршрутизатори (Routers) перевіряють запитуваний URL для знаходження “збігу”
- Якщо збіг знайдено, контролер та метод-дія (Action) виконуються
- Екшен Контролер стає екземпляром і викликається метод, назва якого збігається з ім’ям дії (Action Name)
- Цей метод дії (Action) стане екземпляром і викличе методи з моделей, в залежності від запиту
- Цей контролер потім буде екземпляром об’єкта макету (Layout Object)
- Цей об’єкт макету буде, базуючись на основі деяких змінних запиту і параметрів системи (також відомих як “handles”), створювати набір об’єктів Блоків, які є дійсними для даного запиту
- Макет (Layout) також буде викликати метод виведення у певних об’єктів Блоку (Block), які починають вкладений рендеринг (Блоки будуть містити в собі інші Блоки)
- Кожен Блок корелює з відповідним файлом шаблону (Template). Блоки містять PHP-логіку, а шаблони містять HTML і PHP код для виводу даних користувачеві.
- Блоки звертаються безпосередньо до моделей за своїми даними. Іншими словами, контролер не передає їм структуру даних
Ми, згодом, детальніше оглянемо кожну частину цього процесу, але зараз ми зосередимось на секції Front Controller -> Routers -> Action Controller
Hello World
Досить теорії, дійшла черга до створення Hello World. Ми збираємося:
- Створити модуль Hello World в системі Magento
- Налаштувати цей модуль з маршрутизацією (routes)
- Створити контролер(и) для наших маршрутів (routes)
Створюємо модуль Hello World
По-перше, ми створимо структуру тек для цього модуля. Наша структура тек повинна виглядати наступним чином (ви повинні використовувати свій простір імен):
app/code/local/Alanstormdotcom/Helloworld/Block app/code/local/Alanstormdotcom/Helloworld/controllers app/code/local/Alanstormdotcom/Helloworld/etc app/code/local/Alanstormdotcom/Helloworld/Helper app/code/local/Alanstormdotcom/Helloworld/Model app/code/local/Alanstormdotcom/Helloworld/sql
Потім створюємо конфігураційний файл для цього модуля (за адресою app/code/local/Alanstormdotcom/Helloworld/etc/config.xml
):
<config> <modules> <Alanstormdotcom_Helloworld> <version>0.1.0</version> </Alanstormdotcom_Helloworld> </modules> </config>
Потім створюємо файл для активації модуля (за адресою app/etc/modules/Alanstormdotcom_Helloworld.xml
):
<config> <modules> <Alanstormdotcom_Helloworld> <active>true</active> <codePool>local</codePool> </Alanstormdotcom_Helloworld> </modules> </config>
Нарешті переконуємося, що наш модуль активний:
- Очистіть кеш Magento
- В адміністративній панелі Magento перейдіть до System -> Configuration -> Advanced
- Розгорніть “Disable Modules Output” (Відключення виводу модулів”) (якщо не розгорнуто)
- Переконайтесь, що з’явився модуль
Alanstormdotcom_Helloworld
.
Налаштування маршрутизації
Далі ми збираємося налаштувати маршрутизацію (routes). Маршрутизація буде перетворювати URL-запит в дію (Action Controller) та метод. У Magento, на відміну від інших PHP MVC-систем, ви повинні явно визначати маршрутизацію (routes) в глобальній Magento-конфігурації.
В файл config.xml
додайте наступну секцію:
<config> ... <frontend> <routers> <helloworld> <use>standard</use> <args> <module>Alanstormdotcom_Helloworld</module> <frontName>helloworld</frontName> </args> </helloworld> </routers> </frontend> ... </config>
Тут у нас є багато нових термінів, давайте оглянемо їх.
Що таке <frontend>
?
Тег <frontend>
відноситься до областей (Area) Magento. Зараз думайте про області як про індивідуальні Magento-додатки. Область “frontend” – це зовнішній вигляд додатку Кошика Мадженто. Область “admin” – це приватний додаток адміністративної консолі. Область “install” – це додаток, який ви використовуєте для запуску початкового встановлення Magento.
Чому теги <routers>
налаштовані на індивідуальні маршрути?
Є відома цитата про комп’ютерну науку, яку часто пов’язують з Філом Карлтоном:
“Є лише дві важкі речі в комп’ютерній науці: валідація кешу та йменування речей”
Magento, як і всі великі системи, страждає від проблем надлишкового йменування. Ви знайдете багато місць в глобальному налаштуванні (global config), і в системі в цілому, де іменування інтуїтивно не зрозуміле, або навіть, зовсім неоднозначне. Маршрутизація – одне з таких місць.
Що таке <frontName>
?
Коли маршрутизатор (router) аналізує URL, то він отримує розділені запити
VASH-DOMEN/frontName/actionControllerName/actionMethod/
Тож, при визначені “helloworld” у <frontName>
тезі, ми говоримо Magento, що нам потрібна відповідь URL у вигляді
VASH-DOMEN/helloworld/*
Багато новачків у Magento плутають цей frontName з об’єктом Front Controller. Це не теж саме. FrontName належить виключно до маршрутизації (routers).
Для чого тег <helloworld>
?
Цей тег повинен йменуватись іменем модуля в нижньому регістрі. Наш модуль Helloworld, значить ім’я тега – helloworld. Цей тег, технічно, визначає назву нашого маршруту.
Ви також помітите, що наш frontName співпадає з іменем нашого модуля. Це вільна конвенція, щоб frontName’и збігались із назвами модулів, але це не є обов’язковою вимогою. Насправді, один модуль може визначати декілька <routers>
і, як результат, може мати декілька frontName.
Для чого <module>Alanstormdotcom_Helloworld</module>
?
Цей тег повинен містити повну назву вашого модуля, включаючи ім’я package/namespace
. Це буде використовуватися системою для розташування (визначення) наших файлів контролера.
Створення Action Controller(ів) для наших маршрутів (Routes)
Останній крок, і у нас буде свій контролер. Створіть файл в:
app/code/local/Alanstormdotcom/Helloworld/controllers/IndexController.php
Із наступним змістом:
class Alanstormdotcom_Helloworld_IndexController extends Mage_Core_Controller_Front_Action { public function indexAction() { echo 'Hello World!'; } }
Очистіть кеш та завантажте веб-сторінку за наступним посиланням:
VASH-DOMEN/helloworld/index/index
Також, ви повинні перевірити завантаження сторінок:
VASH-DOMEN/helloworld/index/ VASH-DOMEN/helloworld/
Повинна з’явитись порожня сторінка з текстом “Hello World!”. Вітаємо, ви налаштували свій перший контролер Magento!
Де розміщуються контролери?
Контролери повинні бути розміщені в модулі, у папці “controllers” (назва в нижньому регістрі). Це те місце, де система шукатиме їх.
Як іменувати контролери?
Пам’ятаєте тег <module>
, що міститься в config.xml
?
<module>Alanstormdotcom_Helloworld</module>
Назва контролера буде:
- Починатись з рядка, зазначеного в config.xml (
Alanstormdotcom_Helloworld
) - З подальшим нижнім підкресленням (
Alanstormdotcom_Helloworld_
) - Яке буде супроводжуватися назвою екшен контролера (
Alanstormdotcom_Helloworld_Index
) - І, нарешті, слово “Controller” (
Alanstormdotcom_Helloworld_IndexController
)
Всі Action контролери повинні розширювати клас Mage_Core_Controller_Front_Action
.
index/index
— що це за нонсенс?
Як згадувалося раніше, всі URL в Magento ведуть (за замовчуванням) за адресою
VASH-DOMEN/frontName/actionControllerName/actionMethod/
Таким чином, в URL
VASH-DOMEN/helloworld/index/index
частинка URI “helloworld” – є frontName, за яким слідує індекс (ім’я Action контролера), за яким слідує інший індекс, який є ім’ям Action методу, що буде викликатися. (Екшен index буде викликати метод public function indexAction(){...}
.)
Якщо URL є неповним, Magento використовує “index” за замовчуванням. Тому, наступні адреси є еквівалентними:
VASH-DOMEN/helloworld/index/ VASH-DOMEN/helloworld/
Якби у нас був URL в такому вигляді
VASH-DOMEN/checkout/cart/add
тоді Magento буде:
- Звертатись до глобальної конфігурації, щоб знайти модуль для frontName checkout (
Mage_Checkout
) - Шукати Action контролер кошика (
Mage_Checkout_CartController
) - Викликати метод
addAction
у контролері кошика
Інші прийоми контролера
Давайте спробуємо додати нестандартний метод до нашого контролера. Додайте наступний код в файл IndexController.php
public function goodbyeAction() { echo 'Goodbye World!'; }
і потім перейдіть по URL для перевірки
VASH-DOMEN/helloworld/index/goodbye
Оскільки ми розширюємо клас Mage_Core_Controller_Front_Action
, це дає нам деякі методи безкоштовно. Наприклад, додаткові елементи URL, які автоматично розбираються на пари key/value. Додайте наступний метод до контролера.
public function paramsAction() { echo '<dl>'; foreach($this->getRequest()->getParams() as $key=>$value) { echo '<dt><strong>Param: </strong>'.$key.'</dt>'; echo '<dl><strong>Value: </strong>'.$value.'</dl>'; } echo '</dl>'; }
і відвідайте наступний URL
VASH-DOMEN/helloworld/index/params?foo=bar&baz=eof
Ви повинні побачити виведення кожного параметра та його значення.
Нарешті, що нам потрібно зробити, якщо б ми хотіли URL вигляду
VASH-DOMEN/helloworld/messages/goodbye
Тут ім’я екшен контролера messages, отже ми повинні створити файл в
app/code/local/Alanstormdotcom/Helloworld/controllers/MessagesController.php
з назвою контролера
Alanstormdotcom_Helloworld_MessagesController
і методом, який виглядав би приблизно так
public function goodbyeAction() { echo 'Another Goodbye'; }
І це лишень поверхневий опис того, як Magento реалізує контролерну частину MVC. Хоча це трохи складніше, ніж в інших PHP MVC-фреймворках. Але ця система дуже гнучка, і вона дозволить вам побудувати практично будь-яку структуру URL, яку забажаєте.
Автор: Alan Storm (http://alanstorm.com/magento_controller_hello_world/)
Переклад українською: Ненько Сергій
Адаптація перекладу: SebWeo
Попередня стаття теми: Magento для PHP MVC розробників (Alan Storm) – ч.1/11
- Magento для PHP MVC розробників (Alan Storm) – ч.1/11
- Magento для PHP MVC розробників – розбір Контролера (ч.2/11)
- Magento для PHP MVC розробників – Макети, Блоки та Шаблони (ч.3/11)
- Magento для PHP MVC розробників – Моделі та основи ORM (ч.4/11)
- Magento для PHP MVC розробників – Інсталювання Ресурсу (ч.5/11)
- Magento для PHP MVC розробників – Розширений ORM – EAV (ч.6/11)
- Magento для PHP MVC розробників – Особлива конфігурація системи (ч.7/11)
- Magento для PHP MVC розробників – Поглиблене налаштування системи (ч.8/11)
- Magento для PHP MVC розробників – Колекції Varien Data (ч.9/11)
- Magento для PHP MVC розробників – Перевизначення і оновлюваність системи (ч.10/11)
- Magento для PHP MVC розробників – Конфігурація системи за замовчуванням (ч.11/11)