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 будет:

  • Обращаться к глобальной конфигурации, чтобы найти модуль для 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

 

 

Share

Последние посты

Как выбрать идеальный ноутбук: Полный гайд

Выбор ноутбука может быть сложной задачей в мире, где рынок переполнен вариантами на любой вкус… Читать далее

22/04/2024

Томас Эдисон

Наша самая большая слабость заключается в том, что мы быстро сдаемся. Самый верный способ добиться… Читать далее

20/04/2024

Самые красивые и впечатляющие мосты со всего мира (ТОП-10)

Мост — это нечто большее, чем просто сооружение, соединяющее два берега. Для того, чтобы появился… Читать далее

19/04/2024

Соломон

Жизнь нас учит, что свою пару мы познаем, когда разводимся, своих братьев мы познаем, когда… Читать далее

18/04/2024

Чак Паланик

Кто может — тот делает. Кто не может — тот критикует Чак Паланик   Читать далее

17/04/2024

Ричард Бах

Ни одно желание не дается тебе отдельно от силы, позволяющей его осуществить. Хотя, возможно, для… Читать далее

16/04/2024