Успадкування шаблонів і можливість повторного використання
Механізми повторного використання та успадкування шаблонів підвищують вашу продуктивність, оскільки кожен шаблон містить тільки унікальний вміст, а повторювані елементи та структури використовуються повторно. Ми представляємо три концепції: успадкування макета, горизонтальне повторне використання і успадкування одиниць.
Концепція успадкування шаблонів Latte схожа на успадкування класів у PHP. Ви визначаєте батьківський шаблон, від якого можуть відштовхуватися інші спадкові шаблони і перевизначати частини батьківського шаблону. Це чудово працює, коли елементи мають спільну структуру. Звучить складно? Не хвилюйтеся, це не так.
Успадкування макета {layout}
Давайте розглянемо успадкування шаблонів макета на прикладі. Це
батьківський шаблон, який ми назвемо для прикладу layout.latte
, і він
визначає HTML-скелет документа.
Теги {block}
визначають три блоки, які дочірні шаблони можуть
заповнювати. Усе, що робить тег block, це повідомляє шаблонізатору, що
дочірній шаблон може перевизначити ці частини шаблону, визначивши
свій власний блок із тим самим ім'ям.
Дочірній шаблон може мати такий вигляд:
Ключовим тут є тег {layout}
. Він повідомляє шаблонізатору, що цей
шаблон „розширює“ інший шаблон. Коли Latte рендерить цей шаблон, спершу
він знаходить батька – у цьому випадку layout.latte
.
У цей момент шаблонізатор помітить три блокові теги в layout.latte
і
замінить ці блоки вмістом дочірнього шаблону. Зверніть увагу, що
оскільки дочірній шаблон не визначив блок footer, замість нього
використовується вміст батьківського шаблону. Вміст усередині тега
{block}
у батьківському шаблоні завжди використовується як
запасний варіант.
Виведення може мати такий вигляд:
У дочірньому шаблоні блоки можуть розташовуватися тільки або на верхньому рівні, або всередині іншого блоку, тобто:
Крім того, блок завжди буде створюватися в незалежно від того, чи буде
оточуюча {if}
умова оцінена як true або false. Всупереч тому, що ви
можете подумати, цей шаблон дійсно визначає блок.
Якщо ви хочете, щоб виведення всередині блоку відображалося умовно, використовуйте наступне:
Дані поза блоками в дочірньому шаблоні виконуються до відтворення
шаблону макета, тому ви можете використати його для визначення змінних
типу {var $foo = bar}
і поширення даних на весь ланцюжок
успадкування:
Багаторівневе успадкування
Ви можете використовувати стільки рівнів успадкування, скільки необхідно. Одним із поширених способів використання успадкування макетів є наступний трирівневий підхід:
- Створіть шаблон
layout.latte
, у якому зберігатиметься основний зовнішній вигляд вашого сайту. - Створіть шаблон
layout-SECTIONNAME.latte
для кожного розділу вашого сайту. Наприклад,layout-news.latte
,layout-blog.latte
тощо. Усі ці шаблони розширюютьlayout.latte
і включають стилі/дизайн для кожного розділу. - Створіть окремі шаблони для кожного типу сторінки, наприклад, для новинної статті або запису в блозі. Ці шаблони розширюють відповідний шаблон розділу.
Динамічне успадкування макета
Ви можете використовувати змінну або будь-який вираз PHP як ім'я батьківського шаблону, отже, успадкування може поводитися динамічно:
Ви також можете використовувати Latte API для автоматичного вибору шаблону компонування.
Поради
Ось кілька порад щодо роботи зі спадкуванням макета:
- Якщо ви використовуєте
{layout}
у шаблоні, він має бути першим тегом шаблону в цьому шаблоні. - Макет можна шукати автоматично (як у презентаторах). У цьому
випадку, якщо шаблон не повинен мати макет, він вкаже на це тегом
{layout none}
. - Тег
{layout}
має псевдонім{extends}
. - Ім'я файлу розширеного шаблону залежить від завантажувача шаблонів.
- Ви можете мати стільки блоків, скільки хочете. Пам'ятайте, що дочірні шаблони не зобов'язані визначати всі батьківські блоки, тому ви можете заповнити розумні значення за замовчуванням у кількох блоках, а потім визначити лише ті, які вам потрібні пізніше.
Блоки {block}
Див. також анонімні {block}
Блок дає можливість змінити відображення певної частини шаблону, але ніяк не втручається в навколишню логіку. Давайте розглянемо наступний приклад, щоб проілюструвати, як працює блок і, що важливіше, як він не працює:
Якщо ви відобразите цей шаблон, результат буде точно таким самим із тегами блоку або без них. Блоки мають доступ до змінних із зовнішніх діапазонів. Це просто спосіб зробити його перевизначеним для дочірнього шаблону:
Тепер під час візуалізації дочірнього шаблону цикл
використовуватиме блок, визначений у дочірньому шаблоні child.Latte
,
замість блоку, визначеного в базовому шаблоні parent.Latte
; виконаний
шаблон буде еквівалентний такому:
Однак, якщо ми створимо нову змінну всередині іменованого блоку або замінимо значення існуючої змінної, зміну буде видно тільки всередині блоку:
Вміст блоку може бути змінено за допомогою фільтрів. У наступному прикладі видаляється весь HTML і наводиться заголовок:
Тег також може бути записаний як n:attribute:
Локальні блоки
Кожен блок перевизначає вміст однойменного батьківського блоку. За винятком локальних блоків. Вони чимось схожі на приватні методи в класі. Ви можете створити шаблон, не побоюючись, що через збіг імен блоків вони будуть перезаписані другим шаблоном.
Друк блоків {include}
Див. також {include file}
Щоб надрукувати блок у певному місці, використовуйте тег
{include blockname}
:
Ви також можете вивести блок з іншого шаблону:
Блоки, що виводяться, не мають доступу до змінних активного контексту, за винятком випадків, коли блок визначено в тому самому файлі, куди його ввімкнено. Однак вони мають доступ до глобальних змінних.
Передавати змінні в блок можна наступним чином:
Ви можете використовувати змінну або будь-який вираз у PHP як ім'я
блоку. У цьому випадку додайте ключове слово block
перед змінною,
щоб під час компіляції було відомо, що це блок, а не вставка шаблону, ім'я якого також може бути у
змінній:
Блок також може бути надрукований усередині себе, що корисно, наприклад, під час рендерінгу деревоподібної структури:
Замість {include menu, ...}
можна також написати {include this, ...}
, де
this
означає поточний блок.
Виведений вміст можна змінювати за допомогою фільтрів. У наступному прикладі видаляється весь HTML і ставиться заголовок:
Батьківський блок
Якщо вам потрібно вивести вміст блоку з батьківського шаблону, вам
допоможе оператор {include parent}
. Це корисно, якщо ви хочете
доповнити вміст батьківського блоку, а не повністю його
перевизначити.
Визначення {define}
Крім блоків, у Latte існують також „визначення“. Їх можна порівняти з функціями у звичайних мовах програмування. Вони корисні для повторного використання фрагментів шаблонів, щоб не повторюватися.
Latte намагається зробити все просто, тому в основному визначення – це те ж саме, що і блоки, і все, що сказано про блоки, також стосується і визначень. Цим вони відрізняються від блоків:
- вони укладені в теги
{define}
- вони рендерингуються тільки тоді, коли вставлені
через
{include}
- для них можна визначати параметри, як для функцій у PHP
Уявіть, що у вас є допоміжний шаблон з набором визначень того, як малювати HTML-форми.
Аргументи визначення завжди необов'язкові зі значенням за
замовчуванням null
, якщо не вказано значення за замовчуванням
(тут 'text'
є значенням за замовчуванням для $type
). Типи
параметрів також можуть бути оголошені: {define input, string $name, ...}
.
Шаблон з визначеннями завантажується за допомогою {import}
. Самі визначення виводяться так само, як
і блоки:
Визначення не мають доступу до змінних активного контексту, але мають доступ до глобальних змінних.
Динамічні імена блоків
Latte дає змогу дуже гнучко визначати блоки, тому що ім'я блоку може бути
будь-яким виразом PHP. У цьому прикладі визначено три блоки з іменами
hi-Peter
, hi-John
і hi-Mary
:
Наприклад, ми можемо перевизначити тільки один блок у дочірньому шаблоні:
Таким чином, виведення матиме такий вигляд:
Перевірка існування блоку {ifset}
Див. також {ifset $var}
Використовуйте тест {ifset blockname}
, щоб перевірити, чи існує блок
(або кілька блоків) у поточному контексті:
Як ім'я блоку ви можете використовувати змінну або будь-який вираз у
PHP. У цьому випадку додайте ключове слово block
перед змінною, щоб
було зрозуміло, що перевіряється не вона:
Існування блоків також повертається функцією hasBlock()
:
Поради
Ось кілька порад щодо роботи з блоками:
- Останній блок верхнього рівня не обов'язково повинен мати закриваючий тег (блок закінчується разом із кінцем документа). Це спрощує написання дочірніх шаблонів, у яких один основний блок.
- Для підвищення читабельності ви можете за бажанням дати ім'я тегу
{/block}
, наприклад{/block footer}
. Однак ім'я має збігатися з ім'ям блоку. У великих шаблонах цей прийом допомагає побачити, які теги блоків закриваються. - Ви не можете безпосередньо визначити кілька блокових тегів з однаковим ім'ям в одному шаблоні. Але цього можна домогтися, використовуючи динамічні імена блоків.
- Ви можете використовувати n:attributes для
визначення таких блоків,
як
<h1 n:block=title>Welcome to my awesome homepage</h1>
- Блоки також можна використовувати без імен, тільки для застосування
фільтрів до висновку:
{block|strip} hello {/block}
Горизонтальне повторне використання {import}
Горизонтальне повторне використання – це третій механізм
повторного використання та успадкування в Latte. Він дозволяє
завантажувати блоки з інших шаблонів. Це схоже на створення файлу з
допоміжними функціями в PHP, а потім завантаження його за допомогою
require
.
Хоча успадкування шаблонів є однією з найпотужніших функцій Latte, воно обмежується простим успадкуванням – шаблон може розширювати лише один інший шаблон. Горизонтальне повторне використання – це спосіб досягти множинного успадкування.
Нехай у нас є набір визначень блоків:
За допомогою команди {import}
імпортуйте всі блоки та визначення, визначені в blocks.latte
, в інший шаблон:
Якщо ви імпортуєте блоки з батьківського шаблону (тобто
використовуєте {import}
у layout.latte
), вони будуть доступні у
всіх дочірніх шаблонах, що дуже зручно.
Шаблон, який планується імпортувати (наприклад, blocks.latte
), не
повинен розширювати інший шаблон, тобто
використовувати {layout}
. Однак він може імпортувати інші
шаблони.
Тег {import}
має бути першим тегом шаблону після {layout}
. Ім'я
шаблону може бути будь-яким виразом PHP:
Ви можете використовувати стільки виразів {import}
, скільки
хочете, у будь-якому даному шаблоні. Якщо два імпортованих шаблони
визначають один і той самий блок, перемагає перший. Однак найвищий
пріоритет віддається головному шаблону, який може перезаписати
будь-який імпортований блок.
Вміст перезаписаних блоків можна зберегти, вставивши його так само, як і батьківський блок:
У цьому прикладі {include parent}
буде коректно викликати блок
sidebar
із шаблону blocks.latte
.
Успадкування блоків {embed}
Спадкування блоків переносить ідею успадкування макетів на рівень фрагментів контенту. У той час як успадкування макета працює зі „скелетами документів“, які пожвавлюються дочірніми шаблонами, успадкування одиниць дає змогу створювати скелети для менших одиниць вмісту і повторно використовувати їх у будь-якому місці.
У успадкуванні блоків ключовим є тег {embed}
. Він поєднує в собі
поведінку {include}
і {layout}
. Він дозволяє включати вміст
іншого шаблону або блоку і, за бажанням, передавати змінні, як це робить
{include}
. Він також дозволяє перевизначати будь-який блок,
визначений всередині включеного шаблону, як це робить {layout}
.
Для прикладу ми будемо використовувати елемент складного акордеона.
Давайте подивимося на скелет елемента в шаблоні collapsible.latte
:
Теги {block}
визначають два блоки, які можуть заповнювати дочірні
шаблони. Так, як і у випадку з батьківським шаблоном у шаблоні
успадкування макета. Ви також бачите змінну $modifierClass
.
Давайте використаємо наш елемент у шаблоні. Тут на допомогу
приходить {embed}
. Це супер потужний набір, який дає нам змогу
робити все: включати вміст шаблону елемента, додавати до нього змінні
та додавати до нього блоки з користувацьким HTML:
Висновок може мати такий вигляд:
Блоки всередині тегів embed утворюють окремий шар, незалежний від інших
блоків. Тому вони можуть мати те саме ім'я, що й блок поза embed, і ніяк на
них не впливають. Використовуючи тег include всередині
тегів {embed}
, ви можете вставляти створені тут блоки, блоки з
вбудованого шаблону (які не є локальними), а
також блоки з основного шаблону, які є локальними. Ви також можете імпортувати блоки з інших файлів:
Вбудовані шаблони не мають доступу до змінних активного контексту, але мають доступ до глобальних змінних.
За допомогою {embed}
можна вставляти не тільки шаблони, а й інші
блоки, тому попередній приклад можна написати так:
Якщо ми передаємо вираз у {embed}
і не ясно, що це – блок чи ім'я
файлу, додайте ключове слово block
або file
:
Приклади використання
У Latte існують різні види успадкування та повторного використання коду. Давайте узагальнимо основні поняття для більшої наочності:
{include template}
Use Case: Використання header.latte
і footer.latte
всередині
layout.latte
.
header.latte
footer.latte
layout.latte
{layout}
Приклад використання: Розширення layout.latte
всередині
homepage.latte
і about.latte
.
layout.latte
homepage.latte
about.latte
{import}
Користувацький випадок: sidebar.latte
в single.product.latte
і
single.service.latte
.
sidebar.latte
single.product.latte
single.service.latte
{define}
Приклад використання: Функція, яка отримує деякі змінні та виводить деяку розмітку.
form.latte
profile.service.latte
{embed}
Приклад використання: Вбудовування pagination.latte
в
product.table.latte
і service.table.latte
.
pagination.latte
product.table.latte
service.table.latte