Продовжуючи огляд Magento ми перейдемо до розгляду макетів (Layouts) та блоків (Blocks).
На відміну від багатьох популярних PHP MVC систем, контролер Magento не передає об’єкт даних у View (Відображення) або не задає параметри для об’єкта view. Натомість, компонента View моделі безпосередньо посилається на системні моделі, щоб отримати інформацію, необхідну для відображення.
Одним з наслідків цього дизайнерського рішення є те, що компонента View була розділена на Blocks (блоки) і Templates (шаблони). Blocks – це PHP об’єкти, Template – “сирі” PHP файли, які містять суміш HTML і PHP (де PHP використовується в якості мови програмування для шаблонів). Кожен блок прив’язаний до одного, простого файлу шаблону. Всередині phtml-файлу ключове слово $this
містить посилання на об’єкт блоку шаблона.
Швидкий приклад. Погляньте на шаблон списку товарів за замовчуванням у файлі:
app/design/frontend/base/default/template/catalog/product/list.phtml
Ви побачите наступний код шаблону PHP.
<?php $_productCollection=$this->getLoadedProductCollection(); $_helper = $this->helper('catalog/output'); ?> <?php if(!$_productCollection->count()): ?> <p class="note-msg"><?php echo $this->__('There are no products matching the selection.') ?></p> <?php else: ?>
Метод getLoadedProductCollection
можна знайти в шаблоні блоку,
Mage_Catalog_Block_Product_List
app/code/core/Mage/Catalog/Block/Product/List.php ... public function getLoadedProductCollection(){ return $this->_getProductCollection(); } ...
Метод блоку _getProductCollection
потім створює екземпляри моделі і читає їх дані, повертаючи результат в шаблон.
Реальна сила поєднання Блок/Шаблон (Block/Template) стає явною при використанні getChildHtml
методу. Він дозволяє включати контент другорядного Блок/Шаблон всередину основного Блок/Шаблон.
Блоки викликають Блоки, які викликають Блоки – ось так і буде створено весь HTML-макет для вашої сторінки.
Погляньте на шаблон макета сторінки в одну колонку.
app/design/frontend/base/default/template/page/1column.phtml   <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" > Сам шаблон містить зовсім не багато коду. Тим не менше, кожен виклик$this->getChildHtml(...)
буде підвантажувати та додавати до шаблону ще один блок (Block). Ці блоки, в свою чергу, також можуть використовуватиgetChildHtml
для отримання інших блоків. Ось так блоками і будується весь фінальний шаблон сторінки.Макет (Layout)
Отже, Блоки та Шаблони, це все добре, але вам, ймовірно, цікаво:На ці питання відповідає Макет. Layout (Макет) – це набір XML рядків, який буде визначати, які блоки на сторінці включені, а які блоки не беруть участі при рендерингові. У минулій статті серії ми виводили контент на екран прямо із екшен методів. Цього разу давайте створимо простий HTML шаблон для нашого модуля Hello World. По-перше, створимо файл в
- Як я кажу Magento, який блок я хочу використати на цій сторінці?
- Як я кажу Magento, з якого блоку я повинен почати рендеринг?
- Як мені вказати конкретний блок в
getChildHtml (...)
? Ці рядки не схожі на ім’я мого блоку.app/design/frontend/ПАКЕТ_ТЕМ/ТЕМА/layout/local.xmlз наступним вмістом
<?xml version="1.0" encoding="UTF-8"?> <layout> <default> <reference name="root"> <block type="page/html" name="root" output="toHtml" template="simple_page.phtml" /> </reference> </default> </layout>
Потім створіть файл в
app/design/frontend/ПАКЕТ_ТЕМ/ТЕМА/template/simple_page.phtml
з наступним вмістом (ми використовуємо специфікацію HTML5)
<!DOCTYPE html> <html lang="<?php echo $this->getLang() ?>"> <head> <title>Тест</title> <style type="text/css"> body { background-color: #f00; } </style> </head> <body> </body> </html>
Для запуску процесу створення макету (макетування) із Контролера нам потрібно додати виклики ще двох методів із екшен методу.
public function indexAction() { $this->loadLayout(); $this->renderLayout(); }
Очистіть кеш Magento і перезавантажте сторінку з контролером Hello World (за адресою
VASH-DOMEN/helloworld/index
). Тепер ви повинні побачити веб-сторінку з яскраво-червоним фоновим кольором та HTML кодом, який міститься в шаблоніsimple_page.phtml
.
Що відбувається
Отже, тут багато магії вуду та загадкового чаклунства. Давайте поглянемо на те, що відбувається всередині.
При відкритті сторінки в Мадженто, система створює один великий XML-файл, що містить у собі всі налаштування макету теми (всі теги
<block/>
,<reference/>
та<remove/>
). Коли викликається метод контролераloadLayout
, то Magento буде:
- Створювати цей XML-макет
- Створювати екземпляри класу Блока для кожного тега
<block/>
і<reference/>
, використовуючи в якості класу ім'я атрибутаtype
тега як шлях до глобальних налаштувань, та зберігати їх у внутрішньому масиві об’єктів макету_blocks
, використовуючи ім’я атрибутаname
в якості ключа до масиву.- Якщо тег
<block/>
містить атрибутoutput
, його значення додається до внутрішнього масиву_output
об'єктів макету.
Потім, коли ви викличете в контролері метод
renderLayout
, Magento буде перебирати всі Блоки в масиві_output
, використовуючи значення атрибутуoutput
в якості методу зворотного виклику. Це завждиtoHtml
, і він являє собою відправну точку для виведення цього шаблону блока.У наступних розділах ми оглянемо те, як створюються екземпляри Блоків, як генеруються їх файли макету, і завершимо на процесі виводу.
Створення екземпляру Блока
Отже, в XML-файлі макету тег
<block/>
або<reference/>
має атрибутtype
, що насправді є URI згрупованого імені класу. Тобто, коротким записом імені класу, який використовує Блок.
<block type="page/html" ... <block type="page/template_links" ...
Розташовується URI згрупованого імені класу у файлі глобальної конфігурації. Перша частина URI (до слешу; у наведених вище прикладах
page
) використовується для запиту до глобальної конфігурації, щоб знайти ім'я класу сторінки (page
). Друга частина URI (після слешу) буде додана до назви базового класу, щоб створити ім’я класу, який Magento повинен буде «екземплярувати».Як приклад, оглянемо URI для
page/html
. Спочатку Magento дивиться файл глобальної конфігурації для цього типу:
app/code/core/Mage/Page/etc/config.xml
і знаходить
<page> <class>Mage_Page_Block</class> </page>
Це дає нам ім'я базового класу
Mage_Page_Block
. Потім, друга частина URI (html
) додається до цього імені класу, щоб отримати остаточну назву класу БлокуMage_Page_Block_Html
. Це і буде класом, екземпляр якого буде створено.Якщо ми створимо блок з тим самим ім'ям, як у вже існуючого блока, новий екземпляр блоку замінить оригінальний екземпляр. Це те, що ми зробили в нашому файлі
local.xml
(зверху в статті).
Використання посилань
<reference name="" />
зачепить всі XML декларації, що містяться у вже існуючому блокові із вказаним ім'ям. Всі вузли<block/>
, що включені до посилання (reference), будуть підписані в якості дочірніх блоків до батьківського блоку посилання.<layout version="0.1.0"> <default> <block type="page/html" name="root" output="toHtml" template="page/2columns-left.phtml"> <!-- ... дочірні блоки ... --> </block> </default> </layout>
в іншому файлі макета:
<layout version="0.1.0"> <default> <reference name="root"> <!-- ... інший дочірній блок ... --> <block type="page/someothertype" name="some.other.block.name" template="path/to/some/other/template" /> </reference> </default> </layout>
Незважаючи на те, що кореневий блок (root) оголошується в окремому XML-файлі макета, новий блок додається як дочірній блок. Magento спочатку створює Блок
page/html
з ім'ямroot
. Тоді, коли він пізніше зустріне посилання з тим самим ім'ям (root), він призначить новий блокsome.other.block.name
як дочірній кореневому блокові.
Як генеруються Файли Макетів
Отже, на даний час у нас вже дещо покращилось розуміння того, що відбувається з XML макетом. Але звідки цей XML-файл береться? Щоб відповісти на це питання, ми повинні ввести два нових поняття: Handles (зачіпки) і Package Layout (пакет макетів).
Handles (зачіпки)
Кожен запит сторінки в Magento буде генерувати кілька унікальних зачіпок. Наприклад, для головної сторінки сайту це можуть бути такі зачіпки:
default
,cms_index_index
,customer_logged_out
.Зачіпки містяться в різних місцях в системі Magento. Звернемо увагу на дві зачіпки:
default
іhelloworld_index_index
. Зачіпкаdefault
присутня у кожному запиті в системі Magento. Зачіпкаhelloworld_index_index
створюється шляхом об'єднання назви маршруту (helloworld), назви дії контролера (index) та назви методу дії контролера (index) у єдиний рядок. Це означає, що кожен можливий метод в контролері має пов'язану з ним зачіпку.
Пакет Макетів
Ви можете уявити Пакет Макетів в якості файлу глобальної конфігурації. Це великий XML-файл, який містить всі можливі конфігурації макетів для конкретної системи Magento. Він створюється шляхом об'єднання вмісту всіх файлів XML-макетів для поточної теми. Для теми Мадженто за замовчуванням це вміст усіх файлів у папці:
app/design/frontend/base/default/layout/
За лаштунками цього залишаються секції
<frontend><layout><updates/>
та<adminhtml><layout><updates/>
глобальної конфігурації, які містять вузли з усіма назвами файлів, що повинні завантажуватись у поточну область. Після того, як файли, що перелічені у файліconfig
обробились, Magento об’єднує їх усіх і останнім додає універсальний XML-файл –local.xml
. Це той файл, в якому ви зможете додати свої унікальні налаштування до поточної теми Magento.
Комбінація Зачіпок і Пакету Макетів
Якщо ви подивитеся на файл Макетів, ви побачите деякі знайомі теги, наприклад
<block/>
і<reference/>
, але всі вони огорнуті іншими тегами, наприклад:<default /> <catalogsearch_advanced_index /> ...
Це все теги-зачіпки. Макет сторінки при кожному окремому запиті генерується шляхом захоплення всіх секцій пакету макетів, які збігаються з зачіпками у запиті.
Плюс ще один додатковий тег, про який вам слід знати в пакеті макетів. Тег
<update/>
, що дозволяє включити інші теги-зачіпки. Наприклад:
<customer_account_index> <!-- ... --> <update handle="customer_account"/> <!-- ... --> </customer_account_index>
Ця конструкція означає, що запити до зачіпки
customer_account_index
повинні включати в себе<reference/>
і<blocks/>
з зачіпки<customer_account/>
.
Закріплення вивченого на практиці
Добре, тепер перейдемо від теорії до практики. Давайте повернемося до того, що ми робили раніше. Володіючи новими знаннями, додаємо:
<layout version="0.1.0"> <default> <block type="page/html" name="root" output="toHtml" template="simple_page.phtml" /> </default> </layout>
у файл
local.xml
. Це означає, що ми перевизначили тег "root" іншим блоком. Розміщуючи це в зачіпці<default/>
, ми забезпечили перевизначення, що буде спрацьовувати при кожному запиті сторінки в системі. Це, ймовірно, не те, що нам потрібно.Якщо ви відкриєте будь-яку іншу сторінку на сайті, ви помітите, що вони або порожні або мають той же червоний фоновий колір, що й сторінка модуля "hello world". Давайте змінимо запис у local.xml так, щоб зміни стосувались лише сторінки "hello world". Ми зробимо це, змінивши зачіпку
default
на зачіпку для контролера нашого модуля (тобто,helloworld_index_index
).<layout version="0.1.0"> <helloworld_index_index> <block type="page/html" name="root" output="toHtml" template="simple_page.phtml" /> </helloworld_index_index> </layout>
Очистіть кеш в Magento і решта сторінок повинні оновитись.
Зараз це відноситься тільки до нашого
index
методу. Давайте також протестуємо іgoodbye
метод. У контролері змінюємо екшен методgoodbye
так, щоб це виглядало наступним чином:public function goodbyeAction() { $this->loadLayout(); $this->renderLayout(); }
Якщо ви завантажите наступну адресу, то ви помітите, що як і раніше отримуєте макет Magento за замовчуванням (default):
VASH-DOMEN/helloworld/index/goodbye
Нам потрібно додати зачіпку з повним іменем дії (
helloworld_index_goodbye
) до файлу local.xml. Це дозволить використовувати тегupdate
для зачіпкиhelloworld_index_index
замість того, щоб оголошувати новий<block/>
.
<layout version="0.1.0"> <!-- ... --> <helloworld_index_goodbye> <update handle="helloworld_index_index" /> </helloworld_index_goodbye> </layout>
Завантаження наступних сторінок (після очищення кешу) повинно давати ідентичні результати:
VASH-DOMEN/helloworld/index/index VASH-DOMEN/helloworld/index/goodbye
Початок Виводу та getChildHtml
У стандартній конфігурації вивід починається з Блоку
root
(оскільки він має атрибут виводу –output
). Ми перевизначаємо кореневий шаблон власним
template="simple_page.phtml"Шаблони посилаються на кореневу папку поточної або за замовчуванням (default) теми. Для дефолтної теми це шлях:
app/design/frontend/base/default
Для теми custom (наприклад) це буде шлях:
app/design/frontend/default/custom/template
Тобто, повний шлях до файлу шаблону буде таким:
app/design/frontend/default/custom/template/simple_page.phtml
Пакет тем base є кінцевим місцем призначення для будь-якого шаблону. Якщо Magento не знайде шаблон в будь-якій іншій темі, він повернеться до базової (base). Проте, як уже згадувалося, ви не повинні розміщувати свою тему у цій папці (або ж коригувати файли у ній), оскільки після оновлення Magento всі ваші коригування будуть затерті. Натомість, створюйте свій пакет тем, або ж власну тему у пакеті тем default.
Додавання блоків контенту
Пуста червона сторінка досить нудна. Давайте наповнимо її деяким змістом. Змінюємо зачіпку
<helloworld_index_index/>
вlocal.xml
так, як це вказано нижче:
<helloworld_index_index> <block type="page/html" name="root" output="toHtml" template="simple_page.phtml"> <block type="customer/form_register" name="customer_form_register" template="customer/form/register.phtml"/> </block> </helloworld_index_index>
Ми додаємо новий Блок, що вкладений у кореневий блок
root
. Це блок, який поставляється з Magento – він дозволяє виводити на сторінці форму для реєстрації клієнта. Розмістивши блок у кореневому root блоці, ми зробили його доступним для включення до нашого шаблонуsimple_page.html
. Отже, це дає нам змогу викликати блок в шаблоніsimple_page.phtml
, використовуючи Блоковий методgetChildHtml
. Редагуємо шаблон simple_page.html наступним чином:
<body> <?php echo $this->getChildHtml('customer_form_register'); ?> </body>
Очистіть кеш Magento, перезавантажте сторінку, і ви побачите на сторінці із червоним фоновим кольором форму для реєстрації клієнтів. В Magento також є вбудований Блок з іменем
top.links
. Давайте спробуємо підключити до шаблону і його. Редагуємоsimple_page.html
наступним чином:
<body> <h1>Links</h1> <?php echo $this->getChildHtml('top.links'); ?> </body>
Коли ви перезавантажите сторінку, то помітите, що заголовок
<h1>Links</h1>
рендериться, але нічого не рендериться для блокуtop.links
. Це тому, що ми не додали його вlocal.xml
(або в інший файл XML-макетів). МетодgetChildHtml
може викликати тільки ті блоки, які зазначені як дочірні блоки в макеті. Це дозволяє Magento виводити тільки дійсно потрібні блоки, а також дозволяє вам встановлювати різні шаблони для блоків.Давайте додамо блок
top.links
до нашого local.xml
<helloworld_index_index> <block type="page/html" name="root" output="toHtml" template="simple_page.phtml"> <block type="page/template_links" name="top.links"/> <block type="customer/form_register" name="customer_form_register" template="customer/form/register.phtml"/> </block> </helloworld_index_index>
Очистіть кеш і перезавантажте сторінку. Тепер ви повинні побачити вивід модуля
top.links
(деякі основні посилання системи: наприклад, лінк для логіну на сайт, лінк на кошик та ін.).
Час застосувати action метод
Існує ще одна важлива концепція, яку слід розглянути, перш ніж завершити цей урок, і це тег
<action/>
. Використовуючи тег<action/>
, ми можемо викликати публічні методи PHP класів блоків. Тому замість того, щоб змінювати шаблон кореневого root блоку, замінивши екземпляр блоку на свій власний, ми можемо використовувати виклик методуsetTemplate
.
<layout version="0.1.0"> <helloworld_index_index> <reference name="root"> <action method="setTemplate"> <template>simple_page.phtml</template> </action> <block type="page/template_links" name="top.links"/> <block type="customer/form_register" name="customer_form_register" template="customer/form/register.phtml"/> </reference> </helloworld_index_index> </layout>
Цей код XML макету спочатку встановить шаблон для кореневого root блоку, а потім додасть два блоки, які ми використовуємо як дочірні. Як тільки ми очистимо кеш, результат має виглядати так само, як і раніше. Перевага використання
<action/>
-- це той самий екземпляр блоку, який був створений раніше, а всі його асоціації батьки/нащадки збережуться. З цієї причини це буде більш надійний спосіб впровадження наших змін.
Всі аргументи екшен методу повинні бути огорнуті окремим дочірнім нодом тегу
<action/>
. Ім'я цього ноду (вузла) не має значення, важливий лише порядок вузлів. Ми могли б написати нодaction
з попереднього прикладу наступним чином, що буде мати такий же ефект:
<action method="setTemplate"> <some_new_template>simple_page.phtml</some_new_template> </action>Цей приклад лише для того, щоб проілюструвати, що імена аргументів вузла
action
є довільними.
Підсумок
В цьому уроці ми оглянули основні принципи компонування в Мадженто. Ми оглянули теги
<block/>
,<reference/>
,<update/>
та<action/>
, а також зачіпки оновлень макету, такі як<default/>
та<cms_index_index/>
. Вони складають більшу частину конфігурації макета, що використовується в Magento. Якщо це здається вам трохи складним, не хвилюйтеся, PHP-розробнику Мадженто рідко потрібно працювати з макетами на такому фундаментальному рівні. Magento надає ряд попередньо сконструйованих макетів, які можна модифікувати для досягнення основних потреб інтернет-магазину на цьому двигуні. А розуміння того, як працює вся система макетів, може стати відмінною допомогою, коли ви зіткнетесь із проблемами макетування чи захочете додати нові функції до існуючої системи.
Автор: Alan Storm (http://alanstorm.com/layouts_blocks_and_templates/)
Переклад українською: Ненько Сергій
Адаптація перекладу: SebWeo
Всі статті даної серії:
- 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)
Навчання за кордоном вже давно асоціюється з якісною освітою, новими можливостями та безліччю перспектив. Але…
Вибір майстра для ремонту та перетяжки меблів – завдання, яке потребує вдумливого підходу. Адже від…
Вибір ідеального хостингу під свій сайт може бути досить заплутаною справою, особливо коли існує багато…
Щоб уникати помилок, потрібно набиратися досвіду; щоб набиратися досвіду, потрібно робити помилки Лоуренс Пітер
Коротке визначення Чорного SEO Чорне СЕО (або Чорна оптимізація) — це будь-яка практика, метою якої…
Отримання прав водія категорії C відкриває двері до професійної діяльності, пов'язаної з керуванням вантажними автомобілями.…