Типы шаблонов
Имя шаблона начинается с префикса — он же и решает, откуда шаблон берётся.
| Префикс | Откуда берётся | Пример |
|---|---|---|
@INLINE | код шаблона прямо в строке | view('@INLINE Hello, {$name}') |
@FILE / file: | файл внутри pageblocks_elements_path | view('file:blocks/card.tpl') |
file:<источник>: | файл из именованного источника | view('file:pbShop:chunks/card') |
@PATH / path: | файл по произвольному пути | view('path:assets/chunks/hero') |
| без префикса | чанк MODX (modChunk) по имени | view('header') |
Запаса хода нет
Префикс выбирает один источник, а не порядок перебора. view('header') ищет чанк header и, не найдя его, к файлам не идёт; view('file:header') ищет файл и не смотрит в чанки. Не нашлось — в лог MODX уходит причина с названием источника, в котором искали: [Fenom] chunk 'header' not found in the database; for a file write file:header, — а шаблон отдаёт пустую строку. Пустое место на странице вместо ошибки — это почти всегда оно.
template: в этот список не входит
Шаблон MODX из базы доступен внутри шаблона — {extends 'template:base'}, — потому что template зарегистрирован провайдером Fenom. Но view() и &tpl этот префикс не разбирают: вся строка берётся за имя чанка, и view('template:base') пишет в лог chunk 'template:base' not found in the database и отдаёт пустоту. Держите макет файлом или чанком.
Именованные источники
Компонент или проект один раз регистрирует каталог под именем, и шаблоны зовутся через него — file:<источник>:<путь>:
view('file:pbShop:chunks/card'); // из источника pbShop
{include 'pbShop:chunks/card'} // тот же источник внутри шаблона
[[!pbList? &tpl=`file:pbShop:chunks/card`]]Смысл в том, что путь живёт в одном месте: каталог переехал — правится регистрация, а не все шаблоны, которые на него ссылались. Отдельного параметра пути намеренно нет — источник указывается внутри значения, иначе &tpl, &tplWrapper и &tplEmpty в одном вызове не смогли бы брать шаблоны из разных мест.
Три способа регистрации, все равноправны:
| Кто | Как |
|---|---|
| сам PageBlocks | источник pageblocks — его дефолтные чанки |
| ваш проект | core/App/elements.php, возвращает ['landing' => MODX_BASE_PATH . 'assets/themes/landing/tpl'] |
| компонент-спутник (pbShop, pbAuth) | ElementSources::register('pbShop', $dir) из своего обработчика события — так же, как наполняется ApiRegistry |
use Boshnik\PageBlocks\View\ElementSources;
ElementSources::register('pbShop', MODX_CORE_PATH . 'components/pbshop/elements/chunks');Для спутника есть своё событие — OnPageBlocksSourcesRegister. Оно поднимается при первой сборке реестра, уже после core/App/elements.php, и существует затем, чтобы спутнику не приходилось угадывать, в какой из событий MODX воткнуться:
// Плагин спутника, подписанный на OnPageBlocksSourcesRegister
ElementSources::register('pbShop', MODX_CORE_PATH . 'components/pbshop/elements/chunks');Зарегистрировать можно и позже: спутник грузится после того, как поднялся View, поэтому провайдер Fenom под источник создаётся при первом обращении.
Неизвестный источник — это ошибка, а не путь
file:pbshp:card — опечатка в имени — не превращается в поиск файла с именем pbshp:card. В лог уходит unknown element source 'pbshp' и перечень тех, что зарегистрированы. Имена file, path, template, chunk и inline занять нельзя: они уже значат другое в синтаксисе.
Расширение
Файловым шаблонам (file:, path:) расширение можно не писать — тогда подставится .tpl. Готовые .tpl и .html берутся как есть; любое другое расширение движок расширением не считает и допишет .tpl поверх.
view('file:blocks/article'); // → blocks/article.tpl
view('file:blocks/article.tpl'); // → blocks/article.tpl
view('file:mail/invoice.html'); // → mail/invoice.html📁 Где лежат файловые шаблоны
file: и @FILE отсчитываются от каталога pageblocks_elements_path, по умолчанию это core/App/elements/:
view('file:blocks/article.tpl');
// => ищет: core/App/elements/blocks/article.tplpath: и @PATH — наоборот, несут путь в себе и pageblocks_elements_path игнорируют. Путь пишется от корня сайта или абсолютным, понимает подстановки {core_path}, {base_path}, {assets_path}, и .. в нём запрещены:
view('path:assets/chunks/hero'); // → /assets/chunks/hero.tpl
view('path:{core_path}elements/mail/ok'); // → core/elements/mail/ok.tplЭто тот же механизм, что у поля «Папка чанка» (chunk_path) в блоке: он позволяет держать чанки рядом с кодом, который их использует, а не сваливать всё в один каталог.
Внутри шаблона
Те же префиксы работают в {include}, {extends} и {insert} — это провайдеры движка, а не разбор в view():
{extends 'file:templates/base.tpl'}
{include 'path:assets/chunks/hero'}
{include 'header'} {* без префикса - чанк MODX *}Только файлы
При pageblocks_file_elements_only = true провайдер template: вообще не регистрируется, а чанки из базы перестают быть доступны. Обратите внимание на асимметрию: внутри шаблона {include 'header'} без префикса уходит на файловый провайдер, а view() и &tpl имя без префикса отвергают и пишут об этом в лог — именно в них копипастят вызов сниппета, а имя, которое на одном сайте чанк, а на другом файл, отладить невозможно.