Skip to content

Modifiers

A modifier is the most flexible of the three template extension points. The same modifier works three ways:

fenom
{$title|upper}              {* as a filter     *}
{upper($title)}             {* as a function   *}
{set $t = $title|upper}     {* in an expression *}

That is what separates it from a pseudo-tag, which only works in the first position of a tag and never inside an expression. The rule is simple: need a value — write a modifier; need a chunk of HTML — write a pseudo-tag.

🛠 Your own modifiers

core/App/Helpers/fenom/modifiers.php

The file returns a name → function map:

php
return [
    'upper' => function ($value) {
        return mb_strtoupper((string) $value);
    },
    'excerpt' => function ($text, int $length = 100) {
        return mb_substr(strip_tags((string) $text), 0, $length);
    },
];
fenom
<h2>{$title|upper}</h2>
<p>{$content|excerpt:200}</p>

Arguments after the first are passed with colons: {$x|mod:$a:$b}.

$this->modx is available

The file is included from inside View, so closures in it see $this — meaning $this->modx is the current MODX instance. The global modx() helper works too.

Your file is read after the built-in modifiers, so a modifier with the same name overrides the built-in one. A component upgrade never touches this file.

🔧 Built-in modifiers

Text

ModifierSignatureWhat it does
trim($input, $chars = " \n\r\t\v\0")trims both ends
truncate($input, ['length' => 160, 'suffix' => '...'])strips tags, cuts on a word boundary
ellipsis($input, $length = 100)same, but keeps HTML and repairs unclosed tags
notags($string, $allowable_tags = null)strip_tags()
uppercase($input)aliases: upper, up, strtoupper
lowercase($input)aliases: lower, low, strtolower
preg_replace($value, $pattern, $replacement = '', $limit = -1)value first, not the pattern
split($input, $delimiter = ',')string → array
join($input, $glue = ',')array or iterator → string
decl($number, $forms, $showNumber = false, $sep = '|')plural forms for Slavic languages
date($value, $format = 'j F Y, H:i', $locale = null)$locale = 'ru' gives Russian month and day names
default($input, $fallback)replaces null, '', [] and false
phone($value)keeps digits and +
parseNumber($text)first number in the string
editorjs($json, $options = '')renders Editor.js blocks
print($input, $wrap = true)print_r() inside <pre> — for debugging
ModifierSignatureWhat it does
route($name, $parameters = [])route URL by name, with the language prefix
lang_url($uri = '')prepends the current language prefix to a URL
url($id, $context = '', $args = '', $scheme = -1, $options = [])modX::makeUrl() by resource id
lang($key, $params = [], $language = '')a string from App/lang/
lexicon($key, $params = [], $language = '')a MODX lexicon entry
config($key, $default = null)Config first, then the MODX system setting
placeholder($key)a MODX placeholder

Objects and lists

ModifierSignatureReturns
resource($id, $field = '')one field, or the whole site_content row
user($id, $field = 'username')a user field merged with the profile; 'photo' falls back to a Gravatar, and passwords and sessions are stripped
resources($ids = null, $options = [])a flat list of resources
pbresources($ids = null, $options = [])the same from pb_resources; alias pbResources
users($ids = null, $options = [])a list of users
menu($rootId = 0, $level = 3)a menu tree
blocks($where = [])published blocks in their own order

resources, pbresources and users accept ids as a '12,7,3' string, an array or a number — and then preserve the order of the ids. An associative array as the first argument is read as options: parent, template, context, where, sortby, sortdir, limit, offset. See Helpers.

Nested rendering

ModifierSignatureWhat it does
render($template, $params = [])renders a string as a template (@INLINE)
chunk($template, $data = [])a MODX chunk; understands file: and path:
snippet($name, $params = [])a MODX snippet; !name skips the cache, file:name runs a file
pbJson($data, $options = '')serialisation through the pbJson snippet

Images

ModifierSignature
glide($url, $options = 'fm=webp&q=85')
pthumb($url, $options = [])
phpthumbon($url, $options = [])

JSON and arrays

ModifierSignature
toJSON($array, $options = 320, $depth = 512)
fromJSON($string, $assoc = true, $depth = 512, $options = 0)
slice($array, $start = 0, $length = null)

Assets

cssToHead($css, $media = null), jsToHead($js, $plaintext = false), jsToBottom($js, $plaintext = false), htmlToHead($html), htmlToBottom($html) wrap the MODX regClient* methods. They return nothing and are called for the side effect.

Access

ModifierSignature
isloggedin($ctx = null) — current context by default
isnotloggedin($ctx = null)
ismember($id, $groups = [], $matchAll = false) — empty $id means the current user

In markup the same checks read better as block tags: {auth}, {guest}, {admin}.

Miscellaneous

button(array $button) builds an <a> or a <button> from an array with the keys published, type, caption, classes, href, file, attr, disabled, target_blank, name, value. Without published it returns nothing.

© PageBlocks 2019-present