We launched new forums in March 2019—join us there. In a hurry for help with your website? Get Help Now!
    • 14883 ☆ A M B ☆
    • 450 Posts
    Apologies if this is covered elsewhere - I did try a search, but I may not be savvy enough yet to know how to best find what I’m looking for in the forums.

    In the Evolution API there are methods like getAllChildren(), getActiveChildren(), getDocumentChildren(), getChildIds()... I’m looking for the equivalent of this functionality in Revolution. I see no similar-sounding methods. My hunch is that this is because everything is much more abstracted in Revo(?)

    What I want to do is just write a very simple snippet that will output a list of links for all for all of the child resources of a page... a directory listing basically.

    Any help would be greatly appreciated.
      • 22303 MODX Staff
      • 10,725 Posts
      Quote from: jrotering at Feb 08, 2010, 12:27 PM

      In the Evolution API there are methods like getAllChildren(), getActiveChildren(), getDocumentChildren(), getChildIds()... I’m looking for the equivalent of this functionality in Revolution. I see no similar-sounding methods. My hunch is that this is because everything is much more abstracted in Revo(?)
      Good guess.

      getChildIds() is the same as it was in Evo.

      Here is how I would approach getDocumentChildren()/getAllChildren()/getActiveChildren() in Revo to produce a simple listing Snippet, assuming $parent is the id of the Resource you want to get the children of:
      <?php
      $output = array();
      
      $criteria = $modx->newQuery('modResource', array('parent' => $parent));
      
      // You can set other criteria based on Snippet options or other data
      if (empty($showUnpublished)) $criteria->where(array('published' => true));
      if (empty($showDeleted)) $criteria->where(array('deleted' => false));
      
      // you can limit the amount of memory you use by specifying the fields you need
      if (!empty($fields)) $fields = explode(',', $fields);
      
      // just getting any spaces out of comma-delimited field list
      foreach ($fields as $fieldKey => $field) $fields[$fieldKey] = trim($field);
      
      // now add the fields to the criteria
      $criteria->select('id'); // id is required when retrieving objects with lazy loading
      $criteria->select($fields);
      
      $children = $modx->getCollection('modResource', $criteria);
      foreach ($children as $child) {
          // here we might skip results based on permissions, for instance:
          // if the user does not have permission to "list" a Resource, skip it
          if (!$child->checkPolicy('list')) continue;
      
          // here you can process each child against a Chunk serving as a tpl
          // note again we are limiting the placeholders to be replaced to the specified fields
          $output[]= $modx->getChunk($tpl, $child->get($fields));
      }
      
      return implode("\n", $output);
      ?>

      Note that we are working with objects now, which is important to take advantage of all the new features in Revo, such as the new security model.

      getResources is a good example of this usage as well.
        • 14883 ☆ A M B ☆
        • 450 Posts
        Thanks for the great example. I’m not great with OO syntax but I was able to forge my way through this.

        I wrote a line to set $parent to the current document unless a different doc ID is specified in the snippet call:


        $parent = isset($doc) ? $doc : $modx->documentIdentifier;


        Also, I think that the line

        $criteria->select($fields);


        needs to be modified to

        if ($fields) { $criteria->select($fields); }


        ...otherwise the query syntax gets bungled in cases where there are no custom fields specified.

        With these two small additions I was able to create a "getChildResources" snippet from your example. This would have taken me all week to figure out on my own, and I learn so much more quickly by following real-world examples like this.
          • 28215
          • 4,149 Posts
          Quote from: jrotering at Feb 09, 2010, 11:18 AM

          I wrote a line to set $parent to the current document unless a different doc ID is specified in the snippet call:
          $parent = isset($doc) ? $doc : $modx->documentIdentifier;

          I would recommend this instead, as it’s more proper Revo code:

          $parent = $modx->getOption('doc',$scriptProperties,$modx->resource->get('id'));
          


          Does the same thing, except it’s a bit more proper.
            shaun mccormick | bigcommerce mgr of software engineering, former modx co-architect | github | splittingred.com
            • 22303 MODX Staff
            • 10,725 Posts
            Quote from: jrotering at Feb 09, 2010, 11:18 AM

            Also, I think that the line

            $criteria->select($fields);


            needs to be modified to

            if ($fields) { $criteria->select($fields); }

            Actually, that if should surround both select() calls, i.e.:
            <?php
            if ($fields) {
                $criteria->select('id');
                $criteria->select($fields);
            }
            ?>

            Further, you’d want to use $child->toArray() instead of $child->get($fields) in that case as well, e.g.
            <?php
            $output[]= $modx->getChunk($tpl, !empty($fields) ? $child->get($fields) : $child->toArray());
            ?>

            This is important, because if you only select the id field and then try to get() (or toArray()) any of the fields of the objects other than id, you will issue an additional query to retrieve each additional field. This is called lazy loading and is a feature of xPDO/MODx Revolution, but one that can cause performance issues if you don’t pay attention to how it’s used.