Snippet is caching results

Hi all,

I’m running a tpl in getimagelist and in it I have a custom snippet that loads a user’s extended fields. Below is my snippet call and code. I am calling the getimagelist uncached and the custom snippet uncached.

Snippet Call within GetimageList tpl

[[!getezeeextended?
    &userid=`[[!+userdata_id]]`
]]

Snippet Code

<?php
$userid = (int) $modx->getOption('userid', $scriptProperties);

$usr = $modx->getObject('modUser',$userid);
$profile = $usr->getOne('Profile');
$idx = 1;
if ($profile) {
    $extended = $profile->get('extended');
    $extended['groupid'] = implode(',', $usr->getUserGroups());
    $extended['idx'] = $idx;
    $modx->toPlaceholders($extended, 'ez');
    $idx++;
} else {
    $modx->log(modX::LOG_LEVEL_ERROR,
        'Could not find profile for user: ' .
        $usr->get('username'));
}

return;

The issue I’m getting is that if an extended field is empty or is not defined, it loads the last found field, causing duplicate data. My work around was this

$modx->setPlaceholders(array(
       'my_education' => empty($extended['my_education']) ? "" : $extended['my_education'],
       'my_experience' => $extended['my_experience'],
    ),'ez.');

Moreso this line
empty($extended['my_education']) ? "" : $extended['my_education']

But this is tedious (as I have several extended fields) and I’m sure there is a better way to do this.

What should I do to ensure that $modx->toPlaceholders($extended, 'ez') is always called uncached?

The problem is not that the snippet is called cached or uncached.

The problem is, that the placeholders you created with $modx->toPlaceholders exist, until you overwrite or remove them. If you don’t overwrite them with a new value, they still exist with the value of the previous data-item.

Maybe you can delete all your custom placeholders before setting the new ones:

...
$modx->unsetPlaceholders('ez.'); //delete all placeholders that start with 'ez.'
$modx->toPlaceholders($extended, 'ez');
...

I wasn’t even aware that there was an ‘unsetPlaceholders’… go figure :sweat_smile: This works. Thanks

Ok…there is a new and odd issue now. unsetPlaceholders does clear the placeholders, however it it now loading the last item extended fields and setting it as the placeholders for other items. Let me explain in detail

  • let say getimagelist outputs 5 items
  • item 1 and item 5 has as extended field name called “description”
  • item 2, 3, 4 do not have an extended field name called “description” (extended field not created/set)
  • item 2, 3, 4 uses item 5 extended field name “description” as their placeholder

Any idea why this would happen?

Because the MODX parser uses multiple iterations, it initially doesn’t remove placeholder tags if there exists no corresponding placeholder. The placeholders are left in place to be (possibly) replaced in a later iteration.


If think for a clean solution, you should probably directly use $modx->getChunk('...'); in your custom snippet (instead of setting placeholders).

Or create your own custom version of the snippet “getImageList” and add your additional values to the $fields array before the template-chunk gets parsed.

As halftrainedharry suggests, $modx->getChunk() is the way to go.

It will also speed things up if you use getObjectGraph() to get the user and the profile in a single query (untested):

$users = $modx->getCollectionGraph( 'modUser', '{"Profile":{},"User":{}}', $c);

foreach ($users as $user) {
    $fields = $user->toArray();

    if ($user->Profile) {
        $fields = array_merge($user->Profile->toArray(), $fields);
        $extended = $profile->get('extended');
        $extended['groupid'] = implode(',', $usr->getUserGroups());
        $extended['idx'] = $idx;
        $fields = array_merge($fields, $extended);
        $idx++;
    }
    if ($user->User) {
        $fields = array_merge($user->User->toArray(), $fields);
    }

    unset($fields['password'], $fields['cachepwd'], $fields['salt'], 
        $fields['hash_class']);

    $output  = $modx->getChunk('YourTplChunk', $fields);

    return $output;

Just put your placeholders in the Tpl chunk. You’ll need to add in the placeholder prefix for the fields that use it (if any). You don’t really need the prefix unless the field names might collide with other placeholders on the page.