Magento для PHP MVC розробників – розбір Контролера (ч.2/11)

Архітектура Model-View-Controller (MVC) бере своє походження від мови програмування Smalltalk і Xerox Parc. З тих пір з’явилось багато нових систем, які описують свою архітектуру як MVC. Кожна система різниться, але всі вони ставлять своєю ціллю розділення доступу до даних, бізнес-логіки та інтерфейсу.

Архітектура більшості PHP MVC фреймворків буде виглядати приблизно так:

  1. URL перехоплюється особливим PHP файлом (зазвичай називається Front Controller)
  2. Цей PHP-файл проаналізує URL, отримає ім’я контролера та ім’я дії (Action): цей процес часто називається маршрутизацією (routing)
  3. Отриманий контролер буде в якості нового екземпляра
  4. Отримана назва методу порівнюється з отриманим ім’ям дії (Action), що викликається в контролері
  5. Цей екшен характеризує і викликає методи моделей, залежних від змінних запиту (request)
  6. Метод Екшену (Action) також підготує структуру даних інформації, котра буде передана View
  7. View потім генерує HTML, використовуючи інформацію в структурі даних, отриману від контролера.

У той час, як дана модель є великим кроком вперед (від патерну “кожен файл є сторінкою”, що був на початку), для деяких програмістів це все ще здається “необтесаним”. Загальними претензіями до подібної моделі є:

  • PHP-файл Front Controller’а досі оперує в глобальному просторі імен
  • Збірка над конфігурацією призводить до меншої модульності
    • URL-адреси маршрутизації часто не гнучкі
    • Контролери часто прив’язані до конкретних Views
    • Навіть тоді, коли система пропонує спосіб перевизначення базових значень (defaults), збірка призводить до застосунків, в яких стає важко/неможливо відмовлятися від накопичення все нових моделей, або реалізацій контролера без масивного рефакторингу.

Як ви, напевно, здогадалися, команда Magento поширює цей світогляд і створила більш абстрактний MVC-шаблон, котрий виглядає приблизно так:

  1. URL перехоплюється в окремому PHP файлі
  2. Цей PHP-файл створює екземпляр аплікації Magento
  3. Аплікація Magento створює екземпляр об’єкту Front Controller
  4. Front Controller створює екземпляри будь-якої кількості маршрутів (Router), вказаних в глобальній конфігурації
  5. Маршрутизатори (Routers) перевіряють запитуваний URL для знаходження “збігу”
  6. Якщо збіг знайдено, контролер та метод-дія (Action) виконуються
  7. Екшен Контролер стає екземпляром і викликається метод, назва якого збігається з ім’ям дії (Action Name)
  8. Цей метод дії (Action) стане екземпляром і викличе методи з моделей, в залежності від запиту
  9. Цей контролер потім буде екземпляром об’єкта макету (Layout Object)
  10. Цей об’єкт макету буде, базуючись на основі деяких змінних запиту і параметрів системи (також відомих як “handles”), створювати набір об’єктів Блоків, які є дійсними для даного запиту
  11. Макет (Layout) також буде викликати метод виведення у певних об’єктів Блоку (Block), які починають вкладений рендеринг (Блоки будуть містити в собі інші Блоки)
  12. Кожен Блок корелює з відповідним файлом шаблону (Template). Блоки містять PHP-логіку, а шаблони містять HTML і PHP код для виводу даних користувачеві.
  13. Блоки звертаються безпосередньо до моделей за своїми даними. Іншими словами, контролер не передає їм структуру даних

Ми, згодом, детальніше оглянемо кожну частину цього процесу, але зараз ми зосередимось на секції 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 буде:

  1. Звертатись до глобальної конфігурації, щоб знайти модуль для frontName checkout (Mage_Checkout)
  2. Шукати Action контролер кошика (Mage_Checkout_CartController)
  3. Викликати метод 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

Tags: Magento

Recent Posts

Опалення і гаряча вода коли треба, а не коли включать

Тепло в домі і гаряча вода в будь-який час для багатьох мешканців багатоквартирних та приватних… Read More

19/09/2020

Що краще: цифрове телебачення Т2 чи інтернет-телебачення

Сучасне життя неможливо уявити без телебачення. Воно дозволяє дізнаватися про події в Україні та світі,… Read More

02/09/2020

Гіпоалергенна подушка. Чому вона важлива?

Зараз знайдеться мало людей, в яких немає алергії на продукти або пилок рослин. Вважається, що… Read More

28/08/2020

Футбольний Інстаграм – що нового у топових футболістів

Деякі відомі футболісти ретельно приховують свої особисте життя, а інші – активно постять фотографії з… Read More

24/08/2020

Види та типи компресійних панчіх

Вироби називають компресійними, коли їх застосовують для лікування, а також профілактики порушень кровотоку в нижніх… Read More

22/08/2020

Як правильно замінити оливу у двотактному гідроциклі?

Гідроцикли – це класний плавзасіб, який може подарувати вам незліченні години приємного проведення часу на… Read More

19/08/2020