Stand With Ukraine. Stop Putin. Stop War.

There is something, well, maybe not magical, but certainly productive about using xPDO queries within MODX as opposed to using plain SQL. I've created a really simple snippet which fetches children of a resource (if any) and outputs them in an unordered list. And this took no more than a few minutes to pull off.

Before getting started

You may be wondering what xPDO is. If you've not wrote custom code in MODX Revolution yourself yet, I can imagine the term might not sound familiar. xPDO stands for "open eXtensions to PDO" and it has been developed by part of the MODX Core Development team to provide an Object Oriented Programming approach to relational databases built upon PDO - a core function of PHP > 5.1. At the same time, it also provides (although slightly limited) support for PHP versions under that.

Anyway - that's not what I wanted to explain in this article. This article is about how you can use xPDO within MODX to easily create custom snippets which are very easy to read, fast to execute and can be customized at will without spending years learning a special language - it's all PHP.

getChildren

I designed this snippet cause I needed a simple way to output an unordered list of children of the current resource, but where using an existing addon (like getResources or Wayfinder) would feel like overkill. Of course they both have their own advantages compared to using this custom approach, but I'm being given the power to use this by MODX, it's probably faster (I didn't test it - but just have a look at the lines of code getResources uses and what my snippet uses) and I wont be touching it often after developing it anyway.

This is the actual snippet I'm using:

  // First fetch all the children of the current resource
  $children = $modx->resource->getMany('Children');
  // Check if there are any. If not, return false
  if (!$children) { return false; }
  // Check if there is a tpl set, if not return an error
  $tpl = $modx->getOption('tpl',$scriptProperties,'');
  if (!$tpl) { return 'No template given.'; }
  
  // Start the output
  $o = '<h2>[[*pagetitle]]</h2><ul>'; 
  // Look through the results...
  foreach ($children as $child) {
    // ... fetching the needed info...
    $out = array(
      'id' => $child->get('id'),
      'pagetitle' => $child->get('pagetitle'),
      'menutitle' => $child->get('menutitle'),
      'longtitle' => $child->get('longtitle'));
    // ... and adding it to the output as placeholders in the chunk
    $o .= $modx->getChunk($tpl,$out);
  }
  // Don't forget to close the list
  $o .= '</ul>';

  // Return the output
  return $o;

It's commented line by line, and those familiar with PHP will see what it does in an instant. There's a few things I'd like to point out in this case though:

  1. The script starts off with calling the $modx->resource->getMany('Children') method. What this does is tell MODX to use the current resource, and find associated children based on that resource.
  2. On line 6 shows the modX::getOption (inherited from xPDO:getOption) method, which is considered best practice to get settings and properties from in MODX Revolution. It accepts three parameters:
    1. (string) name of the option (setting, property) you want to retrieve. In this case I'm looking for the tpl parameter.
    2. (options array) variable name you want to get it from. Within snippets you'll use $scriptProperties.
    3. (string) default value if there's no value found for the option name. In this case I set it to an empty string.
  3. When it starts going through each of the children found, it first sets an array with the different resource fields I want to have available in my template chunk, and get the value using the ->get('fieldname') method. When it has all the data in the $out array, it will take those fields and use $modx->getChunk($chunkname,$placeholders) to populate the template with the placeholders, and in turn add that output to the $o variable.
  4. Lastly, it finishes the outer markup and returns the output to the snippet call.
Now let's look at the tpl chunk.

<li>
  <a href="[[~[[+id]]]]" title="[[+longtitle:default=`[[+pagetitle]]`]]">[[+menutitle:default=`[[+pagetitle]]`]]</a>
</li>

The chunk is really straight forward. It creates a list item element, adds in an anchor (hyperlink) tag and uses the placeholders that are set. It also uses the link tag syntax to create a link and the "default" output filter, which sets the value of the placeholder to what's included in the `` quotes if the placeholder value is empty. So in this case, that acts as a backup in case I didn't set a menu or a longtitle (assuming there will always be a pagetitle).

What remains now is showing you how to call it (assuming you named your Snippet getChildren, and your chunk getChildrenTpl):

[[getChildren? &tpl=`getChildrenTpl`]]

Conclusion

Don't be hesistant to coding your own snippets - xPDO and the MODX api makes the most common tasks ridiculously easy. This snippet took a couple of minutes to make and by spending a couple more minutes you could improve it easily to also use an outer template instead of mixing PHP and HTML... but it suited my needs as it is :)

What do you think about using custom coding in your development?

Lefthand Media

Hi Mark,
Nice tut. I would like the same script but for getting sibblings, how would i do that?

Ralph

Mark Hamstra

Hi Ralph,

Thanks for commenting, much appreciated!

If you want to display resources in the same container, you could simply use Wayfinder (though yes, you could also use that for the children :P), or loop through the children of the parent.

So instead of using this:
$children = $modx->resource->getMany('Children');YOu would first get the parent & the children of that: $parent = $modx->resource->getOne('Parent'); $children = $parent->getMany('Children');or like this: $children = $modx->getCollection('modResource',array('parent' => $modx->resource->id));And the rest of the script could stay the same.

Viktorminator

Hello, Mark! Thanks for usefull tuts and for Handyman... Check pls the last tut template in manager (think it's Base template insteat of "Blogpost template")

Rinkesh

Thanks you
for this! Basics well explained, hopefully more advanced examples will follow.

Ian P

This is interesting. Thank you.

I think I'd like to return false not only if there are no children, but also if the children available are all unpublished (or maybe not of a certain tpl type... or whatever). Is this possible?

Unfortunately the documentation for 'getMany' isn't terribly detailed and the API docs seem totally dead. I'm using Rev, maybe there is a better way to do this now? Any feedback would be appreciated :-)

Mark Hamstra

Sorry for taking so long to approve your comment. I need to get some better anti-spam running and re-enable auto submit but am really low on time lately...

You can pass criteria into getMany's second property.

Example:

$modx->resource->getMany('Children', array('published' => true));

Ian P

Thank you Mark, fixed my problem exactly. Incredibly helpful!

Comments are closed :(

While I would prefer to keep comments open indefinitely, the amount of spam that old articles attract is becoming a strain to keep up with and I can't always answer questions about ancient blog postings. If you have valuable feedback or important questions, please feel free to get in touch.