Editorial Note: While everything in this article is still technically valid, we've moved away from developing our own code this way, and instead have been working on a large-scale MODx Extra designed around the premise of multi-context development (multiple client websites within a single MODx instance) and this required a significant refactoring of our own code. For an individual project, however, or even as an intellectual exercise, you may still find the article below quite useful when learning MODx!

We'll introduce you to a few of our favourite Snippets in our Blog, and Conditional just happens to be one of them. Conditional is a snippet that allows us to leverage MODx templating features and will allow us to create our own structure for handling often-repeated content. It should be noted that you likely will only find this snippet as useful as we do if you are developing in a multi-context MODx environment, although it is still useful otherwise. Here's what Conditional looks like under the hood:


*	conditional is a snippet that simplifies conditional chunks, using template variables and system settings as backups
*	conditional types include:
*		'chunk' :		Chunk returns the result of getChunk for a chunk which may or may not be set.
*						If chunk is false, no output is generated.
*						PASS: the name of a template variable which holds the name of an output chunk.
*		'variable' :	Variable acts the same way as chunk, however variable does not store the output inside of a chunk.
*						Instead stores the output directly in a template variable.
*						PASS: the name of a template variable which holds the output.

$debug = false;
$debugDef = 'snippet:conditional';
$resource_fields = array('alias','cacheable','class_key','content','content_type',

/* Capture snippet parameters and existing settings */
$chunk = (string) $modx->getOption('chunk', $scriptProperties, false); // Name of chunk if exists
$variable = (string) $modx->getOption('variable', $scriptProperties, false); // Name of variable if exists
$tpl = (string) $modx->getOption('tpl', $scriptProperties, false); // Wrapper string with a [[+return]] placeholder for output.
$debug = (string) $modx->getOption('debug', $scriptProperties, false); // Debug
if ($chunk) { $mode = 'chunk'; } elseif ($variable) { $mode = 'variable'; } else { return ''; } // Fail gracefully if not all params are present
$setting = (string) $modx->getOption($$mode, $scriptProperties, false);

if($debug) $modx->log(modX::LOG_LEVEL_ERROR,
		'Called with Properties: '.print_r(array('chunk'=>$chunk,'variable'=>$variable,
		'setting'=>$setting), true), '', $debugDef, 'resource '.$modx->resource->id);

if($debug) $modx->log(modX::LOG_LEVEL_ERROR,
		"Proceeding with $mode conditional scheme using the value: ".$$mode, '',
		$debugDef, 'resource '.$modx->resource->id);

/* Communal Pre-Processing*/
$id = $modx->resource->id;
$page = $modx->getObject('modResource',$id);
$resCheck = in_array($$mode,$resource_fields);
$resval = ($resCheck) ? $page->get($$mode) : $page->getTVValue($$mode);
$return = ($resval) ? $resval : $setting;

if($debug) $modx->log(modX::LOG_LEVEL_ERROR,
		"Unprocessed return value is ".$return, '',
		$debugDef, 'resource '.$modx->resource->id);

if($chunk) $return = $modx->getChunk($return);

if(!$tpl) return $return;

if($debug) $modx->log(modX::LOG_LEVEL_ERROR,
		'Returning with a template chunk the following return value: '.print_r(array($return), true),
		'', $debugDef, 'resource '.$modx->resource->id);

$properties = array('return' => $return);
$output = $modx->getChunk($tpl,$properties);
return $output;

To truly understand the need for what we are doing here, let's look at some examples of how this snippet works by taking a look at this page's raw MODx Template, below.

This page's unprocessed MODx template

<html lang="en">
	<meta charset="utf-8" />
	<meta name="viewport" content="width=device-width, initial-scale=1" />
	<div id="page-wrapper">

I know this is a lot of code to process all at once, so let's dive into it. This page is built off of the Atmosphere template from Pixelarity.com (with lots of upgrades of course), which is why you see a lot of the word 'atmosphere' in here. While we won't cover it's use here, wherever you see the snippet [[!notEmailResource]], just be aware that it is a snippet I use to remove certain sections of my template when I'm sending emails using BobRay's EmailResource Extra. This snippet of course does not interact directly with Conditional, so you can ignore it for this discussion.

Using &chunk to Process Chunks with Conditional

The first line of the head tag gives us our first example of Conditional: [[!Conditional?&chunk=`googleAnalyticsChunk`]]. The &chunk= parameter tells Conditional that we want use the appropriate chunk for this given circumstance, and the name of the chunk will be stored in a template variable, in this case `googleAnalyticsChunk`. You might be thinking to yourself, "why not just use a Template variable?" The great thing about Conditional is that if you leave the Template Variable `googleAnalyticsChunk` blank for this resource, Conditional will then look for a System Setting called `googleAnalyticsChunk` to serve in it's place. This simple unextended equivalent of this is of course, [[$[[*googleAnalyticsChunk]]]], which doesn't look for System Settings as a backup source for this chunk!

When using Conditional, Template Variables are used only to override Context Settings, and Context Settings are used to override System Settings. If for example I have a chunk that will be the same for 95% of my clients, I would set the name of the chunk in a System Setting (which applies to every context unless superceded by a Context Setting). For the few clients who require a substitute chunk, I set the name of the chunk in their Context Settings. If there is a single page that requires a substitute chunk, I set the name of the chunk in the Template Variable.

Using &variable to Process Variables with Conditional

For even simpler implementations of Conditional, we can use the &variable= parameter to do the same thing as &chunk=, except that the value is stored directly in the Template Variable or Context Setting or System Setting itself, instead of being stored in a chunk that is referenced by the same. A perfect illustration for this is [[!Conditional?&tpl=`scriptSrc`&variable=`jqueryjsWeblink`]]. Conditional looks for a Template Variable called `jqueryjsWeblink`, and when it realizes it exists but is blank, it looks for the same Context or System Setting. Since every client will use the same (current) version of jQuery, and we want to serve it through a CDN, we simply store the CDN's URL for the current version of jQuery in a System Setting called `jqueryjsWeblink`. This also helps to make site-wide updates of jQuery much easier, as we only have to update it in one place, as opposed to scouring all of our code for every time we reference jQuery.

Using &tpl to Template your Conditional Results

This example also brings us to the &tpl= parameter of Conditional. As web developers, we often find ourselves writing and rewriting the same code over and over again, so why not simplify our template code with even further templating?! In this example, we give Conditional a &tpl= parameter that references the `scriptSrc` chunk. If we ever change the way our javascript files are included, then it is one simple change to a chunk to make that happen. Of course, we have few different template chunks for this purpose, like `scriptSrcLteIE8`, and `metaDescription`. I won't list them all, because it only takes a few chunks to see how things starting making sense:

scriptSrc (chunk)

<script src="[[+return]]"></script>

scriptLink (chunk)

<script src="[[~[[+return]]]]"></script>

scriptSrcIE8 (chunk)

<!--[if lte IE 8]><script src="[[+return]]"></script><![endif]-->

stylesheetLink (chunk)

<link rel="stylesheet" href="[[~[[+return]]]]" />

metaDescription (chunk)

<meta name="description" content="[[+return]]" />

Final Thoughts

If things don't work out quite as you had hoped, use the &debug=`1` parameter to give your MODx Error Log a little more information to show you. One thing you'll notice in Conditional, is that we have included support for using Resource Fields instead of Template Variables. Context & System Settings still backup these fields if they are blank on the resource. It is worth noting that in any environment where you're dealing with Template Variables inside of Snippets, even though Resource Fields and Templates Variables are accessed in the same way within a placeholder tag ( [[*tempvar]] ), they are called differently within Snippet Code. Resource Fields are called using $page->get($resfield), while Template Variables are called using $page->getTVValue($tempvar). We hope this Snippet makes itself useful on your site too!

Chris Holowatyj

Senior Managing Partner at Keddy & Associates

Chris Holowatyj works with local small businesses across Ontario to develop powerful digital marketing strategies that SMBs can actually afford. While focusing on web development as a core area of expertise, Chris also combines his industry knowledge surrounding all things technology - be it Social Media or Graphic Design - to help take small businesses to the next level!

A quick note about Keddy & Associates

Keddy & Associates is a digital marketing agency based in Bradford Ontario, delivering on world-class web design projects at affordable pricing. Keddy & Associates employs a dynamic website templating architecture while customizing end products to meet the specific needs of clients, taking the best of modern web design concepts and conventions, and putting them directly within financial reach of small and medium-sized businesses. Keddy & Associates also develops projects on a less-than-cost basis with not-for-profit organizations, supporting their core values of People, Planet, Profit, through corporate social responsibility commitments and policies. While this article may be informative in nature, not all business decisions are the same, and you should always talk to our competitors so they can quote you an exorbitant price for services we'll do better for cheaper! All kidding aside, it is always good to get a broad base of perspectives for something as incredibly important as your company's website.

Let us take your brand to the next level! Fire off a message to us below so we know you're interested in discussing how we can upgrade or create your website today. We'll give you a free consultation with no obligation and no pressure!