Skip to content

🖼️ View

Класс View в PageBlocks — это обёртка над шаблонизатором Fenom, которая предоставляет простой и мощный способ рендерить шаблоны: чанки MODX, .tpl-файлы, @INLINE-шаблоны и другие.

🚀 Быстрый старт

Вы можете рендерить шаблон с передачей данных:

php
use Boshnik\PageBlocks\Facades\View;
View::make('@INLINE <p>{$title}</p>', ['title' => 'Главная']);

Или с помощью хелпера:

php
view('file:templates/base.tpl', ['title' => 'Главная']);

💡 Пример с контроллером

php
Route::get('/', function () {
    return view('file:templates/base', ['name' => 'PageBlocks']);
    // => ищет: core/App/elements/templates/base.tpl
});

🔧 Пример со сниппетом

Допустим, у вас есть сниппет MyProfile, который выводит профиль текущего пользователя:

php
<?php
$user = $modx->user;
return view('file:blocks/profile.tpl', [
    'username' => $user->get('username'),
    'email'    => $user->getOne('Profile')->get('email'),
]);

Чанк core/App/elements/blocks/profile.tpl:

html
<div class="profile">
    <h2>{$username}</h2>
    <p>Email: {$email}</p>
</div>

📄 Tипы шаблонов

Где ищетсяПример
Инлайновый код шаблона (@INLINE)view('@INLINE Hello, {$name}')
Файловый шаблон (@FILE, file:)view('@FILE blocks/card.tpl')
MODX-шаблон (template:)view('template:base')
По умолчанию: сначала modChunk, потом файлview('header')

Если расширение не указано, по умолчанию добавляется .tpl для файлов.

⚙️ Настройки

НастройкаОписаниеЗначение по умолчанию
pageblocks_elements_pathПуть к файловым шаблонам от папки core/. Используется для @FILE и file: шаблонов.App/elements/
pageblocks_file_elements_onlyЕсли true, шаблоны берутся только из файлов, MODX чанки игнорируются. Повышает производительность.false
pageblocks_fenom_auto_reloadАвтоматическая перекомпиляция шаблонов при изменении файлов. В продакшене можно выключить для лучшей производительности.true

📁 Где хранятся шаблоны

Если вы используете file: или @FILE, путь указывается относительно директории pageblocks_elements_path.

Пример:

php
view('file:blocks/article.tpl');
// => ищет: core/App/elements/blocks/article.tpl

📦 Доступные данные

🧠 $modx

В шаблонах доступен глобальный объект $modx, такой же, как в PHP-коде. Это позволяет обращаться к ресурсам, текущему пользователю и другим системным данным прямо из шаблонов:

🔹 Текущий документ

php
{$modx->resource->id}         {* ID текущей страницы *}
{$modx->resource->pagetitle}  {* Заголовок документа *}
{$modx->resource->get('template')} {* Получение произвольного поля *}

🔹 Текущий пользователь

php
{$modx->user->username}
{$modx->user->id}
{$modx->user->get('email')}
{$modx->user->getGravatar()}

💬 Flash-сообщения

Передаются через сессию $_SESSION['pageblocks']['flash']. В шаблоне доступны:

  • old_input — предыдущие значения полей формы
  • errors — сокращённые ошибки по каждому полю (одга ошибка на каждое поле)
  • errors_full — все ошибки по каждому полю
  • success_message — сообщение об успешном действии
  • error_message — сообщение об ошибке

Примеры:

php
{if $errors.email}
  <p class="error">{$errors.email}</p>
{/if}

<input type="text" name="email" value="{$old_input.email}">

{if $success_message}
  <div class="alert alert-success">{$success_message}</div>
{/if}

{if $error_message}
  <div class="alert alert-danger">{$error_message}</div>
{/if}

Если нужно вывести все ошибки:

php
{foreach $errors_full as $field => $list}
  {foreach $list as $msg}
    <p class="error">{$msg}</p>
  {/foreach}
{/foreach}

💡 Все flash-данные очищаются после первого отображения.

🧩 Модификаторы

PageBlocks расширяет возможности шаблонов Fenom с помощью модификаторов — небольших функций, которые можно применять прямо в шаблонах. Они делают шаблоны лаконичнее и гибче.

🛠 Как добавить свои модификаторы

Вы можете добавить пользовательские модификаторы в файл:

html
core/App/Helpers/fenom/modifiers.php

Этот файл должен возвращать массив вида:

php
return [
    'upper' => function($value) {
        return mb_strtoupper($value);
    },
    'users' => function () {
        return query('modUser')
            ->alias('user')
            ->select('user.*,profile.*')
            ->where(['active' => 1])
            ->join('modUserProfile', 'profile', 'user.id = profile.internalKey')
            ->get();
    },
];

Вызов модификаторов в шаблоне

  • Как фильтр для значения:
php
<h2>{$title|upper}</h2>
  • Как функция:
php
{users()}

Это вернёт список всех активных пользователей с их профилями.

Внутри функции доступна переменная $this->modx — текущий экземпляр MODX.

🔧 Модификаторы по умолчанию

PageBlocks уже содержит множество полезных модификаторов из коробки:

НазваниеОписание
routeПолучить путь по названию маршрута: {route('home')}
langПолучить перевод строки из словаря: {lang('title')}
configПолучить конфиг из Config или MODX: {'site_name'|config}
urlСгенерировать ссылку по ID ресурса: {1|url}
lexiconПолучить фразу из лексикона MODX
resourceПолучить поле или все данные ресурса по ID
userПолучить поле пользователя по ID или текущего
chunkВставить чанк MODX: {'header'|chunk}
snippetВыполнить сниппет MODX: {'getResources'|snippet: ['parents' => 1]}
buttonАвтоматическая генерация кнопки по данным
notagsУдаление HTML-тегов: {notags($text)}
isloggedinПроверка на авторизацию
ismemberПроверка, состоит ли пользователь в группе
phoneОчистка строки до телефонного номера
pbJsonУпрощённый вызов сниппета pbJson для сериализации
cssToHeadПодключение CSS в <head>
jsToBottomПодключение JS в конец документа
preg_replaceРегулярная замена по шаблону
printВывод отладочной информации в <pre>

⚡ Псевдо-теги

Вы можете создавать собственные псевдо-теги (линейные функции), которые вызываются как обычные функции Fenom:

php
{icon 'edit' class='icon-sm'}

Такие теги удобно использовать вместо длинных вставок с insert или include, особенно для повторяемых HTML-фрагментов, как, например, иконки, кнопки или бэйджи.

📁 Где хранить

Создайте файл:

html
core/App/Helpers/fenom/inline_tags.php

В него возвращается массив из имён и функций:

php
return [
    'icon' => function($params) {
        $name = array_shift($params);
        $attrs = [];

        foreach ($params as $key => $value) {
            $attrs[] = htmlspecialchars($key).'="'.htmlspecialchars($value).'"';
        }

        $attrStr = $attrs ? ' ' . implode(' ', $attrs) : '';

        $path = MODX_BASE_PATH . "assets/icons/{$name}.svg";
        if (!file_exists($path)) {
            return "<!-- icon '{$name}' not found -->";
        }

        $svg = file_get_contents($path);
        return preg_replace('/<svg\b(.*?)>/', '<svg$1' . $attrStr . '>', $svg, 1);
    },
];

✨ Примеры в шаблонах

php
{icon 'edit' class='icon-sm text-muted'}
{icon 'user' class='icon-lg' aria-hidden='true'}

Такие функции не требуют объявления через insert или include, проще читаются и легко масштабируются.

🧱 Блочные теги

Блочные теги (block functions) позволяют оборачивать содержимое шаблона в условный блок. Контент внутри такого блока будет отображён только если выполнится заданное условие.

Это особенно полезно, когда нужно контролировать доступ к определённым частям шаблона — например, показывать меню только авторизованным пользователям или только администраторам.

✅ Пример использования

php
{auth}
    <a href="/profile">Профиль</a>
{/auth}

{guest}
    <a href="/login">Вход</a>
{/guest}

В этом примере:

  • Блок {auth} сработает только для авторизованных пользователей.
  • Блок {guest}только для гостей.

🧩 Как добавить свой блочный тег

Блочные теги подключаются из файла:

html
core/App/Helpers/fenom/block_tags.php

В этот файл можно добавить новый тег, например superadmin, который будет отображать контент только для пользователя с ID = 1:

php
return [
    'superadmin' => function (array $params, $content) {
        if ($this->modx->user->id === 1) {
            return $content;
        }
    },
];

📦 Как это использовать

tpl
{superadmin}
    <div class="alert alert-danger">
        Вы супер-админ!
    </div>
{/superadmin}

Контент внутри блока будет показан только если пользователь — супер-администратор.

📘 Как это работает

Блочный тег — это функция, которая получает:

  • $params — параметры, переданные в теге (можно использовать, если нужно),
  • $content — содержимое между открывающим и закрывающим тегом.

🌍 Глобальные переменные

В Fenom можно подключать глобальные переменные, доступные из любого шаблона. Это удобно для хранения статичных данных, настроек или общих значений, например: название проекта, email поддержки, путь до ассетов и т.п.

🛠 Как это работает

Файл core/App/Helpers/fenom/data.php должен возвращать массив с нужными данными:

php
return [
    'package' => 'PageBlocks',
    'support_email' => 'support@example.com',
];

Этот массив будет доступен в шаблонах как глобальный объект $.pb.

📦 Пример использования в шаблоне

php
{$.pb.package}        {* Выведет: PageBlocks *}
{$.pb.support_email}  {* Выведет: support@example.com *}

Глобальные переменные находятся в области pb, поэтому для доступа к ним нужно писать {$.pb.ключ}.

🔐 Функции PHP

По умолчанию Fenom поддерживает ограниченный набор безопасных PHP-функций, которые можно вызывать прямо в шаблонах:

✅ Доступные по умолчанию функции

ФункцияНазначение
count()Подсчёт количества элементов массива
is_string()Проверка, является ли переменная строкой
is_array()Проверка, является ли переменная массивом
is_numeric()Проверка, является ли переменная числом
is_int()Проверка на целое число
constant()Получение значения константы
is_object()Проверка, является ли переменная объектом
gettype()Получение типа переменной
is_double()Проверка на число с плавающей точкой
strtotime()Преобразование строки в метку времени
json_encode()Преобразование данных в JSON
json_decode()Декодирование JSON-строки
ip2long()IP → integer
long2ip()Integer → IP
strip_tags()Удаление HTML-тегов
nl2br()Перевод \n в <br>
explode()Разбиение строки по разделителю
implode()Склеивание массива в строку

🧠 Пример использования

php
{count($items)} элементов
{json_encode(['foo' => 'bar'])}
{strtotime("2025-01-01")}
{strip_tags($html)}

➕ Разрешение дополнительных функций

Вы можете разрешить другие безопасные функции:

core/App/Helpers/fenom/php_functions.php:

php
return [
    'lcfirst',
    'mb_strlen',
    'htmlspecialchars',
];

⚠️ Безопасность

Никогда не разрешайте опасные функции, такие как:

  • eval, exec, system, shell_exec
  • file_get_contents, fopen, unlink

Они могут привести к утечке данных или удалённому выполнению кода.

Разрешайте только чистые и предсказуемые функции, которые не взаимодействуют с файловой системой, сетью или окружением.

🧪 Обработка результата

Третий аргумент метода View::make() или хелпера view() — это обработчик скомпилированного вывода.

Полезно для:

🔹 Удаления HTML

php
view('user-card.tpl', ['user' => $user], function ($buffer) {
    return strip_tags($buffer);
});

📄 Результат: чистый текст без <div>, <a> и других тегов — удобно для текстовых писем.

🔹 Минификация HTML

php
view('page.tpl', [], function ($buffer) {
    return preg_replace('/\s{2,}|\n/', '', $buffer);
});

📉 Убирает пробелы и переносы — ускоряет загрузку страницы.

🔹 Автоматическая цензура

php
view('comment.tpl', ['text' => $comment], function ($buffer) {
    return str_ireplace(['дурак', 'идиот'], '[цензура]', $buffer);
});

🛡️ Применяется при модерации пользовательского контента.

🔹 Замена абсолютных путей

php
view('page.tpl', [], function ($buffer) {
    return str_replace('https://example.com/assets/', '/assets/', $buffer);
});

🔁 Удобно при переносе сайта между окружениями.

🔹 SEO: добавление rel="nofollow" ко всем ссылкам

php
view('page.tpl', [], function ($buffer) {
    return preg_replace('/<a (.*?)href="(.*?)"(.*?)>/i', '<a $1href="$2" rel="nofollow"$3>', $buffer);
});

🔍 Защищает от SEO-спама, особенно в комментариях или гостевом контенте.

🧮 Конструктор запросов

В шаблонах доступен хелпер query() — хелпер для pbQuery. Вы можете выполнять запросы к базе данных прямо из шаблонов Fenom.

📊 Подсчёт записей

php
{query('modResource')->where(['published' => 1])->count()}

📋 Получить список ресурсов

php
{set $resources = query('modResource')
    ->where(['template' => 4])
    ->sortBy('menuindex')
    ->limit(5)
    ->fetchAll()
}
<ul>
    {foreach $resources as $res}
        <li><a href="{$res.uri}">{$res.pagetitle}</a></li>
    {/foreach}
</ul>

🔀 Использовать join

php
{set $users = query('modUser')
    ->alias('u')
    ->where(['u.active' => 1])
    ->join('modUserProfile', 'p', 'u.id = p.internalKey')
    ->select('u.username, p.fullname')
    ->sortBy('u.username')
    ->fetchAll()
}
{foreach $users as $user}
    <p>{$user.username} ({$user.fullname})</p>
{/foreach}

🔍 Найти запись по ID

php
{set $resource = query('modResource')->find(10)}
{if $resource}
    <h2>{$resource->pagetitle}</h2>
{/if}

📂 Получить массив категорий

php
{set $categories = query('modCategory')->fetchAll()}
<ul>
    {foreach $categories as $cat}
        <li>{$cat.category}</li>
    {/foreach}
</ul>

🔧 Использовать value() или pluck()

php
{query('modResource')->where(['id' => 5])->value('pagetitle')}
php
{set $titles = query('modResource')
    ->where(['parent' => 0])
    ->pluck('pagetitle')
}
<pre>{$titles|print}</pre>

📁 Структура файлов

App/
└── Helpers/
    └── fenom/
        ├── modifiers.php         ← Модификаторы
        ├── inline_tags.php       ← Псевдо-теги
        ├── block_tags.php        ← Блочные функции
        ├── data.php              ← Глобальные данные
        └── php_functions.php     ← Разрешённые PHP-функции

🧼 Очистка кэша

Когда вы очищаете кэш через админку MODX, автоматически вызывается:

php
View::clearCache();

Это очищает все скомпилированные шаблоны Fenom.

© PageBlocks 2019-present