Snippets in MODX Revolution - how it works, creation, methods of calling, passing parameters

Snippets in MODX Revolution - how it works, creation, methods of calling, passing parameters

In MODX Revolution CMF, a snippet is a PHP code that can be called in resource fields, chunks, templates, plugins or other snippets. A snippet is used to perform a specific function - data extraction, calculations, data modification, etc.

Usually MODX extras that are responsible for creating site functionality use snippets to call in templates - phpthumb, pdoResources and others.

It is the main tool for adding dynamic content from the database to your pages, manipulating data in the database, or performing complex operations.

Create snippet

Call the context menu by right-clicking in the element tree in the "Snippets" tab of the "Elements" panel. You can use the "Create Snippet" button - then the snippet creation form will open on a new page.

create new snippet page in modx revolution

If you click "Quick Create Snippet", the form will appear in a popup window.

popup form create snippet in modx revolution

You can also use the button to the right of the "Snippets" panel header in the elements tree. The creation form will open on a separate page.

create snippet heading button

If you have the tagElementPlugin package installed, you can create snippets when the quick edit window is called. To do this, select the snippet name in the editor and press Ctrl+Enter.

If a snippet with this name is not found by the script, the system will offer to create a new one.

To avoid confusion in naming with other elements (chunks, plugins, TV), you can use php at the beginning of the name - so it will be easy to understand that you are calling a snippet.

phpArticleGetTags
php.Article.GetTags
php-Article-GetTags
php_Article_GetTags

It's also useful to create a structure in snippet names that looks like an object-oriented model, for example:

php.Article.GetTags
php.Article.UpdateHitsCount
php.Article.GetRating
php.Article.Articles.GetPopular
php.Tags.GetList
php.Author.GetRating

Then elements in the element tree are sorted conveniently. Also in the code in the places where the snipeet is called, there is more understanding of what functionality it has. 

Using

A snippet should always return some value. If it actually returns an empty value, you can return true.

For example, you created the php.snippetName snippet and wrote code that displays the current date and time:

return date("F j, Y, g:i a");

You can call it on a page, template, or other chunk using the syntax:

[[php.snippetName]]

When the page is generated, the result of the snippet execution will be inserted at the location of the tag if the script returns a result.

There are cases when a snippet does not return the result itself, but writes it to placeholders - then you should first call the snippet, and then specify a placeholder in the place where you want to output the result. Let's create the placeholder date:

$modx->setPlaceholder('date', date("F j, Y, g:i a"));

Now you can call it after the snippet:

[[php.snippetName]]
<p>Текущая дата: [[+date]]</p>

Cashing

Snippets can be called in cached and non-cached form.

<!-- cashing -->
[[php.snippetName]]
<!-- non-cashing -->
[[!php.snippetName]]

The cached snippet is saved to a file during the first generation. During the next calls it will be called from the file. This is necessary to reduce the time for script execution and database load. Until the cache of a page, snippet or the whole site is cleared - when you saving a snippet or clearing the site cache, for example.

The non-cacheable snippet will be executed every time the page loads.

The rule is simple - use cached calls wherever you can. Call non-cacheable only when you constantly need actual data or perform an action at the moment of page loading (get $_GET parameters; increase page view count; check user authorization, etc.).

You can also use a non-caching call during the development phase of a website to keep bugs out, but that's not a good idea. After the site is ready, you will have to carefully check a lot of code. It is better to disable element caching in MODX system settings. Go to System Settings & Events, search cache_scripts and set value No.

disable snippet caching in modx revolution

There is an unpleasant nuance - the same snippet on a page called multiple times will return the same result. For example, you have called a snippet that should select a random advertising banner. The same banner will be displayed everywhere on the page. To avoid this, you can pass different parameters to the snippets when calling them - then they will be executed each separately.

Modifiers

A snippet can be used as an output modifier. In short, we can add a modifier to a tag (a chunk or a resource field, for example), and this modifier will change the output value.

MODX has built-in modifiers and filters, but if we want to create our own - we need to use snippets. For example, let's create a phpH1 script that will output the page's pagetitle in the h1 tag:

$input = $modx->getOption('input', $scriptProperties, '');
$output = $input;

if ($output != '') {
	$output = '<h1>' . $output . '</h1>';
}

return $output;

And use it in the template:

[[*pagetitle:phpH1]]

As you guessed, it will return the pagetitle of the page in the h1 tag. But you can write more difficult logic. You can access all the PHP power inside the snippet.

xPDO and MODX API

MODX API is an object-oriented model of our MODX system. It allows you to do all the same actions that you do by hand inside the admin panel, only in the form of php code. And besides there are a lot of useful actions. In a snippet using MODX API you can get fields and TV fields of the current resource:

// resource field
$pagetitle = $modx->resource->get('pagetitle');
// TV value by TV name
$tvValue = $modx->resource->getTVValue('tvName');
// TV value by TV id
$tvValue = $modx->resource->getTVValue(1);

Or another resource by ID:

$resource = $modx->getObject('modResource', 1);
$pagetitle = $resource->get('pagetitle');
$tvValue = $resource->getTVValue('tvName');

We can also build advanced SQL queries against the database using xPDO. xPDO is an object-oriented database model that gives us the convenience and security of SQL queries. xPDO is included in the $modx object. It is similar to PHP PDO, but is an enhanced version written by MODX developers.

For example, get resources with template id=2, and display their titles on the page:

// create a new sql query
$q = $modx->newQuery('modResource');

// add a WHERE condition to the sql query
$q->where(array(
	'template' => '2'
));

// set fields for SELECT
$q->select(array(
	'id', 
	'pagetitle'
));

// get a list of resources that fit our condition
$res = $modx->getCollection('modResource', $q);

// output the pagetitle field of these resources
foreach ($res as $r) {
	echo $r->get('pagetitle');
}

But usually we need more than displaying a list of headers - we want to use some HTML template. Usually chunks are used to template elements in snippets.

Get chunk

The basis of competent development in PHP and MODX is the separation of logic and presentation. You should separate PHP code and HTML layout. As you probably already know, MODX uses chunks for layout. You can get a chunk in a snippet in this way:

$html = $modx->getChunk('tplSomeChunk');

We can also pass to the chunk an array of parameters that will be available in chunk as placeholders.

$html = $modx->getChunk('tplSomeChunk', 
	array(
		'placeholderName' => 'Oleg', 
		'placeholderAge' => 23
	)
);

In the 1st parameter of the $modx->getChunk method we write the name of the chunk, in the second parameter - an array of data that can be used as placeholders in the chunk itself, for example:

<p>Hello, my name is [[+placeholderName]], I'm [[+placeholderAge]] years old.</p>

When we get some data from a database, each row (if we get resources - a row equals a resource) is an array of data. The set of its fields depends on the ones we specified when creating the xPDO query.

[
	0 => [
		'id' => 1,
		'pagetitle' => 'value',
		...
	],
	1 => [
		'id' => 2,
		'pagetitle' => 'value2',
		...
	]
]

So we can pass this data array directly into the second parameter of the chunk call. In this example snippet, we get the resources using the getCollection method and output each of them as a tplSomeChunk chunk:

$output = '';

$q = $modx->newQuery('modResource');
$q->select(array(
    'id',
    'pagetitle'
));
$resources = $modx->getCollection('modResource', $q);

if ($resources) {  
    foreach ($resources as $res) {
        $resArr = $resources->toArray(); // Приводим объект в обычный массив
        $output .= $modx->getChunk('tplSomeChunk', $resArr);
    }
}

return $output;

We used the toArray() method to convert the modResource object into a php array and use it as an argument.

This is because when we use getCollection, getObject and similar methods - we get an array of MODX objects, not a regular php array. When we select a list of Resources using getCollection, we get an array of modResource objects. If we will selecting users - we would get an array of modUsers object with its available methods.

In the example with resources - we need to get exactly the objects, so that the get(), getTVValue() and other methods of resources would be available in our code.

But if we just need to get an array from the database and display it on the page - we can get a data array instead of objects. To do this, create an xPDO query in the same way, but do not pass it to getCollection, but execute it as a regular SQL query.

$output = '';

// create new xPDO query
$q = $modx->newQuery('modResource');
$q->select(array(
	'id', 
	'pagetitle'
));

// make sql query like PHP PDO
$q->prepare();
$q->stmt->execute();
$resources = $q->stmt->fetchAll(PDO::FETCH_ASSOC);

foreach ($resources as $resource) {
	$output = $modx->getChunk('tplSomeChunk', $resource);
}

return $output;

This method increases the speed of the snippet because no MODX objects are created - we use usual PHP arrays.

Parameters

Snippets can also accept input parameters. This allows you to configure different script behavior scenarios. This is similar to the parameters in URLs. To pass parameters, use this syntax:

[[snippetName?
	&parameter1=`value1`
	&parameter2=`[[*pagetitle]]`
	&parameter3=`[[php.My.Snippet]]`
	&parameter4=`[[+placeholder]]`
	&parameter4=`[[++systemVar]]`
]]

Not only static values, but also other snippets, placeholders, resource fields and system variables can be passed into parameter values.

Inside the snippet code, you can access the parameter values using the $modx->getOption() method. When doing so, you can set a default value. For example:

$parameter1 = $modx->getOption('parameter1', $scriptProperties);
// set default value
$parameter2 = $modx->getOption('parameter2', $scriptProperties, 'Привет');

I think we've sorted out all the basic nuances. Snippets help you to take your MODX Revolution sites to the next level and not to experience limitations in development. Therefore, I advise you to learn them.

Please rate this article
(4.5 stars / 2 votes)