We launched new forums in March 2019—join us there. In a hurry for help with your website? Get Help Now!
    • 44437
    • 74 Posts
    I have a TV called engine_type which is a text box and it takes a string value. Using getresources as an example, how can I specify a parent, lets say 15, and the snippet check all of its children TV engine_type value, counts the total number of similiar string values and display it in the format below?

    Engine Type

    Type: 1000cc (5) //5 children resources has a value of 1000cc
    Type: 1200cc (15) //15 children resources has a value of 1200cc
    Type: 2000cc (7) //17 children resources has a value of 2000cc
    Type: 2500cc (1) //1 child resource has a value of 2500cc
    Type: 3000cc (3) //3 children resources has a value of 3000cc

    I hope that my question is not too confusing.

    This question has been answered by dashukin. See the first response.

      • 3749
      • 24,544 Posts
      That would take a custom snippet. Something like this (untested):

      <?php
      $doc = $modx->getObject('modResource', 15));
      $values = array();
      $output = '';
      
      if ($doc) {
      
          $children = $doc->getMany('Children');
          foreach ($children as $child) {
            $tvValue = $child->getTVValue('engine_type');
            if (in_array($tvValue, array_keys($values))) {
                $values[$tvValue] = $values[$tvValue] + 1;
            } else {
                $values[$tvValue] = 1;
            }
          }
          foreach ($values as $key => $value) {
              $output .= '<br />Type: ' . $key . ' (' . $value . ')';
          }
      }
      
      return $output;
        Did I help you? Buy me a beer
        Get my Book: MODX:The Official Guide
        MODX info for everyone: http://bobsguides.com/modx.html
        My MODX Extras
        Bob's Guides is now hosted at A2 MODX Hosting
        • 44437
        • 74 Posts
        Hey BobRay, I have tested the code and it works.

        A few things however.

        1) The snippet only grabs its immediate children (level 0). I understand the logic of your code
        $children = $doc->getMany('Children');// First fetch all the children of the current resource


        How can I grab ALL of the parent id children's children's children's etc?

        I was thinking of doing a getresource call with another getresource call in the tpl. But after thinking it over, it would display the results like

        Type: 1300cc (5)
        Type: 1400cc (2)
        Type: 1300cc (4)
        Type: 1400cc (1)
        etc...

        To get an idea of my resource tree. The hidden resources has the engine_type TV.




          • 3749
          • 24,544 Posts
          That would involve a recursive function (that calls itself). This is probably wrong, but something like this:

          <?php
          
          function process ($children, &$values) {
              foreach ($children as $child) {
                $tvValue = $child->getTVValue('engine_type');
                if (in_array($tvValue, array_keys($values))) {
                    $values[$tvValue] = $values[$tvValue] + 1;
                } else {
                    $values[$tvValue] = 1;
                }
                $moreDocs = $child->getMany('Children');
                if (! empty($moreDocs)) {
                    process($moreDocs);
                }
              }
          
          
          }
          
          $doc = $modx->getObject('modResource', 15));
          $values = array();
          $output = '';
           
          if ($doc) {
              $children = $doc->getMany('Children');
              process($children, $values);
          
              foreach ($values as $key => $value) {
                  if (!empty($key)) {
                      $output .= '<br />Type: ' . $key . ' (' . $value . ')';
                  }
              }
          }
           
          return $output;
            Did I help you? Buy me a beer
            Get my Book: MODX:The Official Guide
            MODX info for everyone: http://bobsguides.com/modx.html
            My MODX Extras
            Bob's Guides is now hosted at A2 MODX Hosting
            • 44437
            • 74 Posts
            Thanks for your help so far. You was right again. The code doesn't work and again I understand its logic. This time I found it to be heavy on the server (due to the recursion) and it yields incorrect data.

            I was looking again at the first snippet that you wrote.

            $doc = $modx->getObject('modResource', 15));


            Instead of using getObject, can it be getCollection?

            My code most likely will be wrong

            $parents = '216,215,408,499,214';
            $doc = $modx->getCollection('modResource', $parents);
            $values = array();
            $output = '';
             
            if ($doc) {
             
                $children = $doc->getMany('Children');
                foreach ($children as $child) {
                  $tvValue = $child->getTVValue('engine_type');
                  if (in_array($tvValue, array_keys($values))) {
                      $values[$tvValue] = $values[$tvValue] + 1;
                  } else {
                      $values[$tvValue] = 1;
                  }
                }
                foreach ($values as $key => $value) {
                    $output .= '<br />Type: ' . $key . ' (' . $value . ')';
                }
            }
             
            return $output;
            
              • 3749
              • 24,544 Posts
              No, you can't do that, but you can do something like this:

              [[SnippetName? &parentList=`216,215,408,499,214`]]




              $parentList = $modx->getOption('parentList', $scriptProperties, '');
              
              $parents = empty($parentList)? array() : explode(',', $parentList);
              $values = array();
              $output = '';
              
              $c = $modx->newQuery('modResource');
              $c->where(array('id:IN' => $parents));
              
              $docs = $modx->getCollection('modResource', $c);
              
              if (! empty($docs)) {
                
                  foreach($docs as $doc) {
                      $children = $doc->getMany('Children');
                      foreach ($children as $child) {
                          $tvValue = $child->getTVValue('engine_type');
                          if (in_array($tvValue, array_keys($values))) {
                              $values[$tvValue] = $values[$tvValue] + 1;
                          } else {
                              $values[$tvValue] = 1;
                          }
                      }
                      
                  }
                  natsort($values);
                  foreach ($values as $key => $value) {
                      $output .= '<br />Type: ' . $key . ' (' . $value . ')';
                  }
              }  
              return $output;

                Did I help you? Buy me a beer
                Get my Book: MODX:The Official Guide
                MODX info for everyone: http://bobsguides.com/modx.html
                My MODX Extras
                Bob's Guides is now hosted at A2 MODX Hosting
              • discuss.answer
                • 46552
                • 2 Posts
                Hi, random_noob! You could try this:

                $engineTypeTVID = 100500; // your TV id
                $carTemplateId = 78; // your car template id
                
                $startParentId = 10;
                $childrenIds = $modx->getChildIds($startParentId, 3, array('context' => 'web'));
                
                $q = $modx->newQuery('modResource');
                $q->leftJoin('modTemplateVarResource', 'eType', array('modResource.id = eType.contentid', 'eType.tmplvarid = ' . $engineTypeTVID ));
                $q->select(array('count(modResource.id)', 'eType.value as eType'));
                $q->where(array(
                 'modResource.id:IN' => $childrenIds,
                 'modResource.template' => $carTemplateId
                ));
                $q->groupby('eType');
                if ($q->prepare() && $q->stmt->execute()) {
                 $rs = $q->stmt->fetchAll(PDO::FETCH_ASSOC);
                 echo '<pre>';
                 print_r($rs);
                 echo '</pre>';
                }
                


                this should do the trick. [ed. note: dashukin last edited this post 9 years, 9 months ago.]
                  • 44437
                  • 74 Posts
                  Thank you guys. Both of these snippets are awesome. I'm sorry for the late response as well. Got caught up developing another website.

                  Anyways, I will play around with these snippets and see what I can learn from them.

                  Cheers
                    • 3749
                    • 24,544 Posts
                    dashukin's snippet would be significantly faster than mine.
                      Did I help you? Buy me a beer
                      Get my Book: MODX:The Official Guide
                      MODX info for everyone: http://bobsguides.com/modx.html
                      My MODX Extras
                      Bob's Guides is now hosted at A2 MODX Hosting
                      • 46552
                      • 2 Posts
                      Quote from: BobRay at Jul 04, 2014, 07:59 PM
                      dashukin's snippet would be significantly faster than mine.
                      Hi, BobRay!
                      Most of the time we don't need full objects but only plain values from database. I think it's better to use such queries in these cases.
                      Cheers!