Skip to content

🛠️ Helpers ​

Helpers are global functions that simplify access to key components of the framework. They are wrappers around core classes and methods commonly used during development.

⚙️ modx() ​

Returns the global instance of modX.

php
$modx = modx();

🧾 query(?string $table = null) ​

Opens a query builder on a table. The name goes without the prefix — the connection adds it. Called with no argument, returns the connection itself.

php
query('site_content')->where('template', 4)->get();
query();  // Illuminate\Database\MySqlConnection

🧱 model(string $name) ​

Opens a query on an Eloquent model resolved under PageBlocks\App\Models\. Unlike query(), rows come back as models — with relations, casts and scopes.

php
model('PbResource')->published()->limit(10)->get();

⚙️ config(string $key, $default = null) ​

Retrieves a value from the configuration.

php
$debug = config('app.debug', false);
// or
Config::get('app.debug', false) 
    ?? $modx->getOption('app.debug', null, false);

📁 Configuration files are stored in: core/App/config/

📥 request(string $key = '') ​

Returns the current HTTP request instance or a specific value.

php
$request = request();            // $request = Request::getInstance()
$name = request('name');         // $request->get('name');
request()->validate([...]);      // $request->validate([...]);

🌐 uri() ​

Returns the current URI without extensions and leading/trailing slashes.

php
$uri = uri();  
// for example: /about.html → "about"
//              /blog/post/ → "blog/post"

🏷️ alias() ​

Returns the current page alias (the last part of the URI).

php
$alias = alias();  
// например: /blog/post → "post"
//           /about → "about"

💾 cache(string $key, $value = null, int $ttl = 3600) ​

Gets or sets a cache value.

php
$data = cache('menu');           // $data = Cache::get('menu');
cache('menu', $items, 600);      // Cache::set('menu', $items, 600);

📤 response($content = '', int $status = 200, array $headers = []) ​

Creates and returns an HTTP response.

php
$response = response();                      // Equivalent to new Response();
return response('OK');                       // $response->text('OK');
return response(['status' => 'ok'], 200);    // $response->json(['status' => 'ok']);

📌 Automatically detects the type: text, json, or object.

✅ validate(array $data, array $rules, array $messages = []) ​

Runs data validation.

php
$validator = validate(
    ['email' => 'john@example.com'],
    ['email' => 'required|email']
);

// or
$validator = Validator::make($data, $rules, $messages);

🖼️ view(string $template, array $params = []) ​

Renders a template with parameters.

php
view('components.card', ['title' => 'Dashboard']);
// or
View::make('components.card', ['title' => 'Dashboard']);

🔁 redirect(...$args) ​

Creates a redirect response.

php
$redirect = redirect();         // $redirect = Redirect::getInstance();
redirect('/login');             // $redirect->to('/login');
redirect()->back();             // $redirect->back();

🧭 route(string $name, array $params = []) ​

Generates a URL from a named route, carrying the current language prefix.

php
$url = route('post.show', ['id' => 10]);   // /en/post/10

Not the same as Route::route()

Route::route() is the bare path with no prefix — that is what route_path() gives you. Reaching for the facade instead of the helper is how links on /en/ end up pointing at the default language.

🌍 lang(string $key, array $replace = [], string $locale = '') ​

Retrieves a translated string.

php
lang('messages.welcome'); 
// or
Lang::get('messages.welcome');

📁 Language files are stored in: core/App/lang/{locale}/

🔐 auth(string $context = '') ​

Checks if the user is authenticated in the given or current context.

php
if (auth()) {
    echo 'You are authenticated';
}

// or

if (auth('en')) {
    echo 'Authenticated in "en" context';
}

🔁 Equivalent to:

php
$modx->user && $modx->user->isAuthenticated($context ?: $modx->context->key);

❌ abort(int $code = 404, string $text = '') ​

Aborts execution and returns an error response.

php
abort(403, 'Access denied'); 
// or
response()->abort(403, 'Access denied')->send();

📄 console($message, $array = []) ​

Writes to the MODX log. The second argument is printed with print_r — handy for an array.

php
console('Order failed', $payload);

⚠️ dd($message, $array = []) ​

Not what you think. This is not Laravel's "dump and die": the page does not stop and nothing is printed to the screen. The function is identical to console() — it logs and carries on.

php
dd('got here', $data);   // ends up in core/cache/logs/error.log

🌍 Languages ​

FunctionWhat it returns
language()The current language, or null
languages()Every active language
langs()A ready set for a language switcher
lang_url(string $uri = '')An address carrying the current language prefix
multilingual()Whether multilingual is on
context()The language key, or the default context when there is none
php
{if multilingual()}
    {foreach langs() as $item}
        <a href="{$item.url}">{$item.name}</a>
    {/foreach}
{/if}

🔀 route_path(string $name, array $parameters = []) ​

Builds the address of a named route — so you neither type it by hand nor hunt down every occurrence when the route moves.

php
route_path('cargo.show', ['id' => 42]);

👤 profile() ​

The current user's profile as an array. A guest gets an empty array, and the result is remembered for the request.

Why not $modx->user

The MODX user row itself holds almost nothing: email, fullname and the extended fields live on the profile. profile() saves you a $user->getOne('Profile') every time.

🛡️ csrf() ​

A ready hidden field with the token, to drop into a form.

html
<form method="post">
    {csrf()}
</form>

🧾 lexicon($key, $namespace = '') ​

A string from the MODX lexicon. Given a namespace, it is loaded for you.

php
lexicon('pb_blocks', 'pageblocks');

🔢 plural_form($number, array $forms) ​

Agreement between a number and a word. Three forms for Russian, two for English.

php
plural_form(5, ['товар', 'товара', 'товаров']);   // товаров
plural_form(2, ['item', 'items']);                 // items

🏳️ Site mode ​

FunctionWhat it does
site_mode()dev or prod
is_dev(), is_prod()The same thing, as a condition

The mode comes from the pageblocks_site_mode setting; anything but dev reads as prod.

📚 Object lists ​

FunctionWhat it returns
resources($ids = null, array $options = [])MODX resources from site_content
pbresources($ids = null, array $options = [])Custom resources from pb_resources
users($ids = null, array $options = [])Users

The same lists are available in templates as modifiers — see View.

🌐 http_post(string $url, $data = null, array $headers = [], int $timeout = 10) ​

A POST request outwards without wiring up curl yourself. Returns the response as an array.

php
http_post('https://api.example.com/hook', ['id' => 42], ['Authorization: Bearer …']);

🕒 now(string $timezone = null) ​

The current moment as a Carbon instance — with all its date arithmetic.

php
now()->addDays(7)->toDateTimeString();

🧷 asset(string $path) ​

URL of a file under assets/, versioned by its modification time:

fenom
{asset('themes/css/main.css')}
<!-- /assets/themes/css/main.css?v=1785440855 -->

Sites are usually deployed without a build step and link their styles with no version, so a returning visitor gets fresh markup against a cached stylesheet. A ?v= taken from mtime fixes that without changing anything in the templates. If the file is not on disk you get the plain URL back, with no version.

For .css and .js a .min sibling wins ​

main.css becomes main.min.css when such a file exists and is no older than the source. So the template always links the readable name, and a site that never runs a build loses nothing.

The mtime check is the safety catch

Edit the source and forget to rebuild, and you get your fresh change unminified rather than the stale minified copy. Silently serving the old one would be worse.

It depends only on MODX constants, not on the site's App layer, so it works in any project running the component.

© PageBlocks 2019-present