Dynamic Search Criteria for getResources

Using a small utility snippet to create complex search criteria for the &where property of getResources or pdoResources or any other snippet that uses a &where property.

There are many cases where the search criteria you want to specify for getResources, pdoResources, or another extra that uses a &where property, require calculations or are too complex to enter off the top of your head. In this article we'll look at a way to use a snippet to create them for you.

We'll use getResources as an example, but this method will work for any &where property.

The Method

The getResources &where property is a JSON string specifying search criteria for getResources to use in selecting resources. Sometimes, you can just create the JSON string yourself, but in other cases, you can use a snippet or placeholder to provide the &where property:

[[getResources? &where=`[[CalculatedWhere]]` . . .]]

The work of creating the value for the &where property is done in a snippet called "CalculatedWhere". Here's an easy example that you could create yourself if you understand JSON. It gets all resources that are published and not deleted:

/* CalculatedWhere snippet */
$c = array(
    'published' => 1,
    'deleted' => 0,
return $modx->toJSON($c);

Note that the keys and values in the array are separated, not by an equals sign, but by the => array assignment operator and the lines in the array all end with a comma. The resulting property in the tag would look like this:

&where = `{"published":1,"deleted":0}`

More Examples

In the next example, we'll get published, not-deleted resources created by the current logged-in user. You still might be able to write your own &where property using a userinfo tag, but this will be faster and easier:

/* CalculatedWhere snippet */
$c = array(
    'published' => 1,
    'deleted' => 0,
    'createdby' => $modx->user->get('id'),
return $modx->toJSON($c);

The example above would produce something like this property in the tag:

&where = `{"published":1,"deleted":0,"createdby":12}`

Here's one that would be almost impossible without a snippet. It gets all resources published during a specified month of a particular year.

[[getResources? &where=`[[CalculatedWhere? &month=`January` &year=`2015`]]` . . .]]

$month = $scriptProperties['month'];
$year = $scriptProperties['year'];
$a_date = $month . ' ' . $year;
$min = strtotime($a_date);
$time = date("Y-m-t 23:59", $min);
$max =  strtotime($time);

$where = array(
    'publishedon:>=' => $min,
    'publishedon:<=' => $max,

return $modx->toJSON($where);

The method used above is a little tricky (actually it's tricky as hell). What we want is to calculate one Unix timestamp for midnight at the beginning of the specified month and another for one second before midnight on the last day of the month. The first is easy, it's the $min calculation in line four. The next line uses the fact that the "t" token of the date() method evaluates to the number of the last day of the month, so $time will be set to one second before midnight on the last day of the month, regardless of the number of days in the month. For February, 2015, $time will be 2015-02-28 23:59. For January, it will be 2015-01-31 23:59. The $max calculation simply converts $time into a Unix timestamp. The resulting JSON string looks like this for January, 2015:


Using a Placeholder

There may be cases where a snippet tag in the getResources call doesn't work properly because of the parsing order. Another strategy is to put a placeholder tag in the getResources &where property and have your snippet set a placeholder.

[[getResources? &where=`[[+CalculatedWhere]]` . . .]]

In the snippet, then, just do this (the snippet tag must be above the placeholder tag on the page):

$jsonString = $modx->toJSON($myArray);
$modx->setPlaceholder('CalculatedWhere', $jsonString);

If you have more than one getResources call on the page, you can add a property to the snippet tag to specify the placeholder that will be set:

[[SetWhere? $month=`January` &year=`2015 &ph=`January`]]
[[getResources? &where=`[[+January]]` . . .]]


[[SetWhere? $month=`February` &year=`2015 &ph=`February`]]
[[getResources? &where=`[[+February]]` . . .]]

Then in the snippet:

$placeholderName = $scriptProperties['ph']
// ...

$modx->setPlaceholder($placeholderName, $value);

Speeding Things Up

If the values sent to the snippet won't change, or won't change very often, you can just write a utility version of the snippet that simply returns the JSON string. Then you can paste that string as the value of the getResources &where property.


The methods described here can fail under some circumstances when getResources is called in a chunk (especially if it's called more than once). You can experiment with calling the snippet cached or uncached, but there will be some cases where it just won't work, although you may be able to fix it by moving the getResources call up into the template or the page content.

More Information on xPDO Query Where

The &where property is used by a number of MODX extras. Because they all use xPDO to retrieve the data, they will always take any valid xPDO criteria as long as they are in JSON format. There is documentation here along with some excellent examples. To generate a &whereproperty, you don't need all the query language, just the array inside the parentheses following the word "where" (which may have other arrays inside it).

Comments (2)

  1. Susan OttwellJan 07, 2015 at 08:44 PM

    $first = mktime(0, 0, 0, $month, 1, $year);
    $last = mktime(23,59,59,$month + 1,0,$year);


  2. Helmut FrühinsfeldJan 08, 2015 at 02:13 AM

    Thank you, that came in just at the right moment! Very helpful...

Please login to comment.