Fenom — это мощный, быстрый и гибкий шаблонизатор для MODX, который заменяет стандартные теги [[...]] на более удобный синтаксис с фигурными скобками {...}. Он интегрируется через компонент pdoTools, ускоряет разработку до 30–50%, позволяет писать циклы, условия и модификаторы прямо в шаблонах, сокращая количество чанков и запросов к БД. Ниже разберём всё от установки до продвинутых возможностей: синтаксис, модификаторы, работу с TV и пользователями, примеры для реальных проектов и типичные ошибки.
- Что такое Fenom и зачем он нужен в MODX
- Установка и настройка Fenom
- Шаг 1: Установка pdoTools
- Шаг 2: Системные настройки (путь: Система → Настройки → pdoTools)
- Шаг 3: Проверка
- Базовый синтаксис Fenom
- Таблица-шпаргалка: сравнение синтаксиса MODX и Fenom
- Практические примеры использования
- Доступ к полям ресурса
- Работа с TV-параметрами и специальными плейсхолдерами
- Примеры использования плейсхолдеров и выражений
- Условия {if}
- Switch/case
- Циклы {foreach}
- Комментарии и экранирование
- Работа с пользователями
- Использование системных настроек
- Модификаторы Fenom в MODX
- Типичные ошибки и подводные камни
- Конфликт фигурных скобок с JavaScript и JSON
- Забыли очистить кеш после включения Fenom
- Включили опасные настройки на продакшене
- Плейсхолдеры с точками и дефисами не работают
- Смешивание синтаксиса MODX и Fenom снижает производительность
- Заключение
Что такое Fenom и зачем он нужен в MODX
Fenom — это standalone-шаблонизатор на PHP, похожий на Twig/Smarty, но легче и быстрее. В MODX он появился в 2015 году с pdoTools 2.0 и стал стандартом для сложных шаблонов.
Преимущества Fenom в MODX:
- Скорость: компилирует шаблоны в PHP-код, кэширует их. На больших сайтах ускорение до 30–50%.
- Удобство: циклы
{foreach}, условия{if}, модификаторы| modifierвместо громоздких сниппетов. - Массивы и объекты: прямой доступ к
$_modx->resource,$_modx->configбез[[*...]]. - Безопасность: экранирование по умолчанию, защита от инъекций.
- Совместимость: работает с 90% существующих чанков (pdoTools парсит MODX-теги внутри Fenom).
Минусы:
- Требует установки дополнения pdoTools.
- Фигурные скобки конфликтуют с JS/JSON (решается
{*комментарии*}илиmodParser). - Непривычно для новичков.
Важно: Fenom появился в MODX с pdoTools 2.0 в 2015 году и полностью совместим с MODX Revolution 3.x через pdoTools 3.x.
Когда использовать Fenom:
- Сложные шаблоны (списки товаров, блоги, формы).
- Проекты на pdoTools (pdoResources, pdoMenu, pdoPage).
- Когда нужно меньше чанков и быстрее рендер.
Установка и настройка Fenom
Fenom работает только с pdoTools (версия 3.x+ для MODX 3).
Шаг 1: Установка pdoTools
- Перейдите в Управление пакетами → найдите pdoTools → Установить.
- Автоматически установятся Fenom и связанные сниппеты.
Шаг 2: Системные настройки (путь: Система → Настройки → pdoTools)
Вот ключевые опции (префикс pdotools_):
| Настройка | Значение | Описание |
|---|---|---|
pdotools_fenom_default |
Yes | Fenom для чанков pdoTools (включено по умолчанию). |
pdotools_fenom_parser |
Yes/No | Fenom для всех страниц/шаблонов сайта (рекомендуем Yes для новых проектов). |
pdotools_fenom_php |
No | PHP-функции в шаблонах (опасно, только для dev). |
pdotools_fenom_modx |
No | Доступ к {$_modx}, {$pdoTools} (опасно). |
pdotools_fenom_options |
{"auto_escape":true} |
JSON опции Fenom (экранирование, include). |
pdotools_fenom_cache |
Yes | Кэш скомпилированных шаблонов (для продакшена). |
parser_class |
pdoParser | Только для продвинутых: переключает весь MODX на pdoParser. Нужен только если включена pdotools_fenom_parser |
Важные уточнения по настройкам:
pdotools_fenom_default— работает только для чанков, вызываемых через pdoTools (pdoResources, pdoMenu, pdoPage и т.п.). Безопасно включать на любых проектах.pdotools_fenom_parser— включает Fenom для всех страниц сайта (контент ресурсов, шаблоны). Требует осторожности на существующих проектах.pdotools_fenom_phpиpdotools_fenom_modx— опасные настройки! Дают доступ к PHP-функциям и полному объекту$modxпрямо из чанков. Включайте только на dev-окружении и для доверенных администраторов.parser_class— менять наpdoParserнужно только если хотите использовать Fenom на всём сайте вместе сpdotools_fenom_parser. Иначе оставьте стандартныйmodParser.
Рекомендуемые настройки для новых проектов:
pdotools_fenom_default: Yespdotools_fenom_parser: Yes (для использования Fenom везде)pdotools_fenom_cache: Yes (для продакшена)pdotools_fenom_php: No (безопасность)pdotools_fenom_modx: No (безопасность)pdotools_fenom_options:{"auto_escape":true,"force_include":true}parser_class: pdoParser (если включилиpdotools_fenom_parser)
Для существующих проектов: включайте только
pdotools_fenom_defaultи не меняйтеparser_class— это позволит использовать Fenom в новых чанках pdoTools без риска поломать старую разметку.
После изменений: Очистить кеш (Система → Очистить кеш).
Шаг 3: Проверка
Создайте чанк testFenom:
{$_modx->resource.pagetitle | upper} (ID: {$_modx->resource.id})
Вызовите: [[!pdoResources? &tpl=`testFenom`]].
Если работает — Fenom активен.
Базовый синтаксис Fenom
Fenom использует синтаксис {...} вместо классических тегов MODX [[...]]. Доступ к данным MODX реализован через специальные переменные $_modx (объект modX), $_pls (плейсхолдеры с точками/дефисами) и обычные переменные для простых плейсхолдеров.
Таблица-шпаргалка: сравнение синтаксиса MODX и Fenom
| Назначение | Классический MODX | Fenom |
|---|---|---|
| Поле ресурса | [[*pagetitle]] |
{$_modx->resource.pagetitle} или {$_modx->resource['pagetitle']} |
| Плейсхолдер | [[+placeholder]] |
{$placeholder} или {$_pls['placeholder']} (для имён с точками или тире) |
| Чанк | [[$header]] |
{$_modx->getChunk('header')} или {include 'header'} или {'header' | chunk} |
| Системная настройка | [[++site_name]] |
{$_modx->config.site_name} или {'site_name' | config} |
| Ссылка на ресурс | [[~15]] |
{$_modx->makeUrl(15)} или {15 | url} |
| Лексикон | [[%lexicon_key]] |
{$_modx->lexicon('lexicon_key')} |
| Вызов сниппета | [[snippetName? ¶m=`value`]] |
{$_modx->runSnippet('snippetName', ['param' => 'value'])} или {'snippetName' | snippet : ['param' => 'value']} |
| Переменная шаблона (TV) | [[*tvname]] |
{$_modx->resource.tvname} или {$_modx->resource['tvname']} |
| Модификатор вывода | [[*field:modifier=`param`]] |
{$field | modifier : 'param'} (модификатор должен быть зарегистрирован как сниппет) |
| Условный оператор | [[If? &subject=`[[*field]]` &operator=`eq` &operand=`value` &then=`...`]] |
{if $resource.field == 'value'} ... {else} ... {/if} |
| Цикл | [[pdoResources? &parents=`0` &tpl=`rowTpl`]] (через сниппет) |
{foreach $_modx->getResources(['parents' => 0]) as $res} {$res.pagetitle} {/foreach} |
| Поле пользователя | [[+modx.user.id]] (после вызова сниппета вроде Login) |
{$_modx->user.id} или {$_modx->user['fullname']} |
| Поле ресурса по ID (FastField) | [[#15.pagetitle]] |
{var $res = $_modx->getResource(15)} {$res.pagetitle} |
| Присвоение переменной | [[setPlaceholder? &name=`var` &value=`value`]] (через сниппет) |
{var $var = 'value'} или {var $date = 'dateAgo' | snippet : ['input' => '2023-01-01']} |
| Доступ к глобальным массивам | [[getServerInfo? &key=`REQUEST_URI`]] (через сниппет) |
{$$ .server.REQUEST_URI} или { $$.get.query} |
Практические примеры использования
Доступ к полям ресурса
Поля текущего ресурса доступны через объект $_modx->resource. Можно использовать как свойства или массив для имен с спецсимволами.
<h1>{$_modx->resource.pagetitle}</h1>
<div class="content">{$_modx->resource.content}</div>
<div class="intro">{$_modx->resource['introtext']}</div>
{* Доступ как к массиву *}
<p>Дата публикации: {$_modx->resource.publishedon | date : 'd.m.Y'}</p>
Работа с TV-параметрами и специальными плейсхолдерами
TV-параметры доступны через массив $_modx->resource:
{* Обычный TV-параметр *}
<div class="price">{$_modx->resource.price}</div>
{* TV-параметр с точками или дефисами в имени *}
{set $specialTV = $_modx->resource['tv-name-with-dashes']}
<div>{$specialTV}</div>
Для работы с плейсхолдерами, установленными через сниппеты, используйте переменную {$_pls}:
{* Установка плейсхолдера в сниппете *}
{set $_pls['page.title'] = 'Новое название'}
{* Вывод плейсхолдера *}
<h2>{$_pls['page.title']}</h2>
Примеры использования плейсхолдеров и выражений
<!-- Плейсхолдер из сниппета --> {$pagetitle}
<!-- TV текущего ресурса --> {$_modx->resource.my_tv}
<!-- С конкатенацией строк --> "Страница: " ~ $_modx->resource.pagetitle
<!-- Тернарный оператор для значения по умолчанию --> {$image ?: '/no-photo.jpg'}
<!-- Сложный тернарный с условием --> {$price > 1000 ? 'Дорогой' : 'Доступный'} товар
<!-- Арифметические операции --> {$quantity * $price | number : 2}
<!-- Доступ к массиву --> {$user['email']}
Важно: переменная $_pls нужна для доступа к плейсхолдерам с точками или дефисами в именах, так как Fenom компилирует переменные в PHP, который не поддерживает такие символы. Для обычных имён используйте просто {$variable}.
Условия {if}
Условные конструкции позволяют динамически отображать контент на основе проверок. Поддерживаются логические операторы, сравнения и вложенные условия.
{* Простое условие *}
{if $id == 1} Главная {elseif $id > 10} Блог {else} Другое {/if}
{* Логические операторы (AND, OR, NOT) *}
{if $user.id > 0 && $_modx->hasPermission('save')} Редактировать {/if}
{if $isAdmin || $isModerator} Админ-панель {/if}
{if !$isEmpty} Содержимое {/if}
{* Сравнение строк и чисел *}
{if $status == 'active'} Активен {else} Неактивен {/if}
{if $count <= 5} Мало элементов {elseif $count <= 20} Средне {else} Много {/if}
{* Вложенные условия *}
{if $user.id} {if $user.group == 'admin'} Полный доступ {else} Ограниченный доступ {/if} {else} Гость {/if}
Switch/case
Альтернатива множественным if-elseif для проверки одного значения на несколько вариантов. Поддерживает default для случаев по умолчанию.
{switch $type}
{case 'news'} Новости {/case}
{case 'blog'} Блог {/case}
{case 'shop'} Магазин {/case}
{default} Другое {/default}
{/switch}
{* С несколькими case на один блок *}
{switch $code}
{case 200} {case 201} Успех {/case}
{case 404} Не найдено {/case}
{default} Ошибка {/default}
{/switch}
Циклы {foreach}
Циклы позволяют итерировать по массивам или объектам. Поддерживаются ключи, индексы, else для пустых коллекций и break/continue.
{* Простой цикл по массиву *}
{foreach $products as $product}
<div>{$product.name} — {$product.price | number : 2} руб.</div>
{/foreach}
{* С индексом и ключом *}
{foreach $items as $key => $item}
{$key + 1}: {$item.title} (ID: {$item.id})
{/foreach}
{* Обработка пустого массива *}
{foreach $comments as $comment}
<p>{$comment.text}</p>
{foreachelse} Нет комментариев
{/foreach}
{* С break и continue *}
{foreach $numbers as $num}
{if $num % 2 == 0} {continue} {/if} {* Пропустить четные *}
{$num}
{if $num > 10} {break} {/if} {* Прервать после 10 *} {/foreach}
{* Вложенный цикл *}
{foreach $categories as $cat}
<h3>{$cat.name}</h3>
{foreach $cat.products as $prod} - {$prod.name} {/foreach}
{/foreach}
Комментарии и экранирование
Комментарии не рендерятся в выводе. Экранирование предотвращает выполнение тегов MODX внутри Fenom.
{* Это однострочный комментарий, не рендерится *}
{* Многострочный комментарий. Можно описывать логику. *}
<!-- Экранирование тегов MODX/JS -->
{* [[!pdoResources]] *} {* Не выполнится как сниппет *}
{* <script>alert('test');</script> *} {* Не выполнится как JS *}
{* Игнорирование блока для стилей/скриптов *}
{ignore} <style> .header { color: red; } </style> {/ignore}
Работа с пользователями
Объект $_modx->user предоставляет доступ к данным авторизованного пользователя, включая профиль и разрешения.
{* Проверка авторизации пользователя *}
{if $_modx->user.id}
<div>Добро пожаловать, {$_modx->user.fullname}!</div>
<p>Email: {$_modx->user.email}</p>
{if $_modx->user.photo} <img src="{$_modx->user.photo}" alt="Фото"> {/if}
{if $_modx->hasPermission('edit_document')} <a href="edit">Редактировать</a> {/if}
{else} <div>Пожалуйста, авторизуйтесь</div> <a href="{ $$.php.url}?service=login">Войти</a>
{/if}
Использование системных настроек
Системные настройки доступны через $_modx->config или модификатор | config.
<title>{$_modx->config.site_name} {if $_modx->resource.pagetitle?}- {$_modx->resource.pagetitle}{/if}</title>
<meta name="description" content="{$_modx->config.site_description}">
<link rel="stylesheet" href="{$_modx->config.assets_url}css/style.css">
<p>Валюта: {'currency' | config}</p>
Модификаторы Fenom в MODX
Fenom поддерживает встроенные модификаторы (унаследованные от Smarty), а также интеграцию с MODX output modifiers через pdoTools . Модификаторы применяются к переменным с помощью символа |, например: {$var | modifier : 'param'} . Параметры передаются через двоеточие.
Важно: не все модификаторы встроены в Fenom «из коробки». Некоторые реализованы как сниппеты MODX и требуют регистрации через параметр &fenomModifiers в вызове pdoTools-сниппетов. Ниже приведена таблица с основными модификаторами.
| Модификатор | Описание | Пример в Fenom |
|---|---|---|
| upper, ucase, uppercase, strtoupper | Преобразует строку в верхний регистр. | {$text | upper} → «HELLO WORLD» |
| lower, lcase, lowercase, strtolower | Преобразует строку в нижний регистр. | {$text | lower} → «hello world» |
| truncate | Обрезает строку до указанной длины, добавляя суффикс (по умолчанию «…»). Параметры: длина, суффикс. | {$long_text | truncate : 10 : '...'} → «Long tex…» |
| ucwords | Делает первую букву каждого слова заглавной. | {$title | ucwords} → «Hello World» |
| ucfirst | Делает первую букву строки заглавной. | {$name | ucfirst} → «Hello» |
| escape, esc | Экранирует специальные символы (HTML, JS и т.д.). Параметры: ‘html’, ‘url’, ‘quotes’ и др. | {$html | escape : 'html'} → «<div>» |
| strip_tags, striptags, stripTags, notags | Удаляет HTML-теги. Можно указать разрешенные теги. | {$html | strip_tags : '<p><a>'} → текст без тегов, кроме p и a |
| replace | Заменяет подстроку на другую. Параметры: ‘from==to’. | {$text | replace : 'old==new'} → замена «old» на «new» |
| date | Форматирует Unix-временную метку в дату (использует strftime). | {$timestamp | date : '%Y-%m-%d'} → «2023-01-01» |
| nl2br | Преобразует новые строки (\n) в теги <br>. | {$text | nl2br} → текст с <br> вместо \n |
| ellipsis | Обрезает строку и добавляет многоточие, если длина превышает указанную (по умолчанию 100). | {$description | ellipsis : 50} → «Short desc…» |
| limit | Ограничивает строку указанным количеством символов (по умолчанию 100). | {$text | limit : 20} → первые 20 символов |
| urlencode | Кодирует строку для URL. | {$query | urlencode} → «hello%20world» |
| urldecode | Декодирует URL-кодированную строку. | {$encoded | urldecode} → «hello world» |
| strtotime | Преобразует строку даты в Unix-временную метку. | {$date_str | strtotime} → 1672531200 |
| ago | Выводит время «назад» (секунды, минуты, часы и т.д.). | {$timestamp | ago} → «2 часа назад» |
| md5 | Генерирует MD5-хеш строки. | {$password | md5} |
| number, number_format | Форматирует число с разделителями (по умолчанию: 0 десятичных, запятая для тысяч, точка для десятичных). | {$price | number : 2 : ',' : '.'} → «1.234,56» |
| cat, append, after | Добавляет строку в конец (если обе не пустые). | {$num | cat : ' books'} → «5 books» |
| prepend, before | Добавляет строку в начало (если обе не пустые). | {$num | prepend : 'Book #'} → «Book #5» |
| default, ifempty, empty, isempty | Возвращает значение по умолчанию, если переменная пустая. | {$name | default : 'anonymous'} → «anonymous» если $name пусто |
| contains | Проверяет, содержит ли строка подстроку, и выводит «then» или «else». | {$text | contains : 'word' : 'Yes' : 'No'} → «Yes» если содержит «word» |
| eq, is, equals (и аналоги: ne, gt, lt и т.д.) | Условные сравнения (равно, не равно, больше, меньше). Используется с then/else. | {$num | eq : 5 : 'Five' : 'Not five'} → «Five» если $num == 5 |
| memberof, ismember | Проверяет, является ли пользователь членом группы. | {$_modx->user.id | memberof : 'Administrator'} → true если в группе |
| userinfo | Возвращает поле пользователя по ID. | {$_modx->user.id | userinfo : 'username'} → имя пользователя |
| Выводит экранированную переменную (дополнительный в некоторых пакетах). | {$var | print} → экранированный вывод |
|
| config | Доступ к системной настройке MODX. | {'site_name' | config} → значение настройки site_name |
| resource | Доступ к полю ресурса по ID. | {15 | resource : 'pagetitle'} → заголовок ресурса с ID 15 |
| url | Генерирует URL ресурса по ID. | {15 | url} → «/page-url» |
| snippet | Вызывает сниппет с параметрами. | {'snippetName' | snippet : ['param' => 'value']} |
| chunk | Вставляет чанк. | {'header' | chunk} |
Встроенные (работают без настройки):
- Работа со строками:
upper,lower,trim,truncate,ucwords,ucfirst,strip_tags,replace,nl2br,split,join - Форматирование:
escape,urlencode,urldecode,base64_encode,base64_decode - Числа и хеши:
number_format,md5,sha1,crc32 - JSON:
json_encode,json_decode - Массивы:
count,join,split
Требуют регистрации через сниппеты MODX:
- MODX-специфичные:
config,resource,url,chunk,snippet,lexicon - Пользовательские:
userinfo,memberof,isloggedin - Временные:
ago,dateAgo(нужно указать&fenomModifiers=dateAgo« в pdoResources) - Кастомные модификаторы из ваших сниппетов
Пример регистрации модификатора-сниппета:
[[!pdoResources?
&fenomModifiers=`dateAgo,myCustomModifier`
&parents=`0`
&tpl=`@INLINE {$pagetitle} ({$publishedon | dateAgo})`
]]
Примечания:
- Модификаторы можно цепочкой комбинировать:
{$text | lower | truncate : 50}. - В MODX любые сниппеты можно использовать как модификаторы через параметр
&fenomModifiersв вызове pdoTools-сниппетов. - Для полного списка встроенных Smarty-подобных модификаторов смотрите официальную документацию Fenom.
Типичные ошибки и подводные камни
Конфликт фигурных скобок с JavaScript и JSON
Fenom использует {...} для своих тегов, что может конфликтовать с JS-кодом или JSON-данными.
Решения:
- Комментарии Fenom: оборачивайте JS/JSON в
{* ... *}или{ignore} ... {/ignore} - Выносите скрипты в отдельные файлы вместо inline-кода
- Используйте
<script src="..."></script>для подключения JS
Пример:
{ignore}
<script>
var config = {
"key": "value",
"array": [1, 2, 3]
};
</script>
{/ignore}
Забыли очистить кеш после включения Fenom
После изменения настроек pdotools_fenom_* обязательно очищайте кеш MODX. Иначе старые версии чанков будут продолжать работать.
Путь: Система → Очистить кеш → Очистить кеш сайта.
Включили опасные настройки на продакшене
Никогда не включайте на боевом сайте:
pdotools_fenom_php(доступ к любым PHP-функциям из чанков)pdotools_fenom_modx(доступ к полному объекту$modx, можно удалить весь сайт)
Эти настройки только для dev-окружения и доверенных администраторов.
Плейсхолдеры с точками и дефисами не работают
Если у вас TV или плейсхолдер с именем вроде my-tv или page.title, используйте $_pls:
{* Неправильно *}
{$my-tv} {* Ошибка синтаксиса *}
{$page.title} {* Ищет свойство объекта *}
{* Правильно *}
{$_pls['my-tv']}
{$_pls['page.title']}
Смешивание синтаксиса MODX и Fenom снижает производительность
Когда в одном чанке используются и [[...]] и {...}, запускаются оба парсера — сначала Fenom, потом modParser. Это замедляет работу.
Рекомендация: переводите чанки полностью на Fenom или полностью оставляйте на классических тегах MODX. Смешанный синтаксис используйте только для плавной миграции.
Заключение
Fenom — это современный, быстрый и удобный шаблонизатор для MODX Revolution 2.x и 3.x, который интегрируется через компонент pdoTools. Вы научились:
- Устанавливать и настраивать Fenom через системные параметры pdoTools.
- Использовать базовый синтаксис Fenom: переменные, условия
{if}, циклы{foreach}, модификаторы|. - Работать с данными MODX через
$_modx->resource,$_modx->user,$_modx->config. - Применять модификаторы для форматирования строк, дат, чисел и других данных.
- Избегать типичных ошибок: конфликтов с JS, забытого кеша, опасных настроек.
Используя Fenom вместе с pdoTools (pdoResources, pdoMenu, pdoPage), вы можете полностью перевести проект на современный, быстрый и гибкий шаблонизатор, значительно упростить поддержку кода и ускорить рендер страниц до 30–50%.
Лучшие практики работы с Fenom:
- Не смешивайте классический синтаксис MODX
[[...]]и Fenom{...}в одном чанке — это замедляет работу. - Выносите повторяющиеся куски в отдельные чанки через
{include 'chunkName'}. - Регистрируйте кастомные модификаторы через параметр
&fenomModifiersпри вызове pdoTools-сниппетов. - Используйте
$_plsдля плейсхолдеров с точками и дефисами в именах. - Никогда не включайте
pdotools_fenom_phpиpdotools_fenom_modxна продакшене. - Очищайте кеш после любых изменений настроек Fenom.
С этими знаниями вы готовы создавать сложные, производительные и легко поддерживаемые шаблоны для MODX.






