We launched new forums in March 2019—join us there. In a hurry for help with your website? Get Help Now!
    • 24629
    • 370 Posts
    Hi all
    im trying to get a collection of pages with specific TV values.
    based on a submitted form i want the query to be more specific i have this
    $criteria = $modx->newQuery('modResource');
    $criteria->innerJoin('modTemplateVarResource', 'TemplateVarResources');
    $criteria->innerJoin('modTemplateVar', 'TemplateVar', 'TemplateVarResources.tmplvarid = TemplateVar.id');
    
    $criteria->where(array('published' => 1,
        'template' => 4,
        'deleted' => 0
    ));
    
    if (isset($_POST["jaartal"]) && $_POST["jaartal"] != '0') {
        $criteria->where(array(
            'TemplateVar.name' => 'startjaar',
            'TemplateVarResources.value' => $_POST["jaartal"]
        ),xPDOQuery::SQL_AND);
    }
    
    if (isset($_POST["categorie"]) && $_POST["categorie"] != '0') {
        $criteria->where(array(
            'TemplateVar.name' => 'categorie',
            'TemplateVarResources.value' => $_POST["categorie"]
        ),xPDOQuery::SQL_AND);
    }
    $docArray = $modx->getCollection('modResource', $criteria);


    now each of the where clauses for TV 'jaartal' or 'categorie' works. But when both of them need to be active (eg. get me the pages that have a 'jaartal'=2013 AND 'categorie'=food) the collection is empty.
    is the build up of the query ok? or does it need to be done different?

    tnx Rdg.

    PS yes there are pages with 2013 and food
      • 3749
      • 24,544 Posts
      Try this:

      $criteria->andCondition(array(
          'TemplateVar.name' => 'categorie',
          'TemplateVarResources.value' => $_POST["categorie"],
          )
      );
        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
        • 24629
        • 370 Posts
        Hi BobRay,

        Nope unfortunately that doesn't work. I tried to understand GetResources but that's a bit to complex.

        Any other ideas? anyone?

        Tnx Rdg

          • 18373 ☆ A M B ☆
          • 3,141 Posts
          Defining xPDOQuery::SQL_AND on the xPDOQuery->where is unneccessary; it defaults to that.

          You'll have to join the TV tables multiple times for each individual TV you are matching, so you can target them specifically.

          Something along these lines (but untested)..

          $criteria = $modx->newQuery('modResource');
          $criteria->innerJoin('modTemplateVarResource', 'CategoryTemplateVarResources', 'modResource.id = CategoryTemplateVarResources.resource');
          $criteria->innerJoin('modTemplateVar', 'CategoryTemplateVar', 'CategoryTemplateVarResources.tmplvarid = CategoryTemplateVar.id AND CategoryTemplateVar.name = \'categorie\'');
          
          $criteria->innerJoin('modTemplateVarResource', 'JaartalTemplateVarResources', 'modResource.id = JaartalTemplateVarResources.resource');
          $criteria->innerJoin('modTemplateVar', 'JaartalTemplateVar', 'JaartalTemplateVarResources.tmplvarid = JaartalTemplateVar.id AND JaartalTemplateVar.name = \'startjaar\'');
          
          ...
          
          if (isset($_POST["categorie"]) && $_POST["categorie"] != '0') {
              $criteria->where(array(
                  'CategoryTemplateVarResources.value' => $_POST["categorie"]
              ),xPDOQuery::SQL_AND);
          }
           


          You can lose the modTemplateVar joins if you are happy with just matching on the TV ID and adding that to the modTemplateVarResource joins.
            Mark Hamstra • Developer spending his days working on Premium Extras and a MODX Site Dashboard with the ability to remotely upgrade MODX and extras to make the MODX world a little better.

            Tweet me @mark_hamstra, check my infrequent blog at markhamstra.com, my slightly more frequent ramblings at MODX.today or see code at Github.
            • 4172
            • 5,888 Posts
            to generate a query for filtering Resources by TV-values you can can use a function like that (most parts stolen from getResources):
            https://github.com/Bruno17/MIGX/blob/master/core/components/migx/model/migx/migx.class.php#L1325
              -------------------------------

              you can buy me a beer, if you like MIGX

              http://webcmsolutions.de/migx.html

              Thanks!
              • 24629
              • 370 Posts
              @Mark, Nope i can't get your example to work. probably due to the fact that i don't fully understand what it does.

              @Bruno, Tnx but that's way too complex for me. I can't see what is being passed to the function nor where the getcollection() is

              Isn't there a $modx->ExtendedGetCollection() somewhere that allows for an array of TVfilters?

              Rdg
                • 24629
                • 370 Posts
                Hi,
                @Bruno. How can i make
                'TemplateVarResources.value:LIKE' => '%'.$_POST["trefwoord"].'%'

                with your tvFilters? i tried
                $tvFilters = "description==projectleider";
                and
                $tvFilters = "description=inArray=projectleider";
                


                but both don't seem to work
                  • 4172
                  • 5,888 Posts
                    -------------------------------

                    you can buy me a beer, if you like MIGX

                    http://webcmsolutions.de/migx.html

                    Thanks!
                    • 24629
                    • 370 Posts
                    @ Bruno: Tnx yes it does help a bit. I'm still confused about the build up of EXISTS especialy what s been done in
                    $criteria->condition($criteria->query['where'][0][1], $cond, xPDOQuery::SQL_AND, null, $cGroup);


                    I can't find any documentation on condition or query['where'][0][1]
                      • 4172
                      • 5,888 Posts
                      doesn't something like that do it?

                      You could of course also load the migx-class, if you have it installed and use its tvFilters - function

                      <?php
                      
                      if (!function_exists('tvFilters')) {
                          function tvFilters($tvFilters = '', &$criteria) {
                              global $modx;
                              
                              $tvFilters = !empty($tvFilters) ? explode('||', $tvFilters) : array();
                              if (!empty($tvFilters)) {
                                  $tmplVarTbl = $modx->getTableName('modTemplateVar');
                                  $tmplVarResourceTbl = $modx->getTableName('modTemplateVarResource');
                                  $conditions = array();
                                  $operators = array(
                                      '<=>' => '<=>',
                                      '===' => '=',
                                      '!==' => '!=',
                                      '<>' => '<>',
                                      '==' => 'LIKE',
                                      '!=' => 'NOT LIKE',
                                      '<<' => '<',
                                      '<=' => '<=',
                                      '=<' => '=<',
                                      '>>' => '>',
                                      '>=' => '>=',
                                      '=>' => '=>');
                                  foreach ($tvFilters as $fGroup => $tvFilter) {
                                      $filterGroup = array();
                                      $filters = explode(',', $tvFilter);
                                      $multiple = count($filters) > 0;
                                      foreach ($filters as $filter) {
                                          $operator = '==';
                                          $sqlOperator = 'LIKE';
                                          foreach ($operators as $op => $opSymbol) {
                                              if (strpos($filter, $op, 1) !== false) {
                                                  $operator = $op;
                                                  $sqlOperator = $opSymbol;
                                                  break;
                                              }
                                          }
                                          $tvValueField = 'tvr.value';
                                          $tvDefaultField = 'tv.default_text';
                                          $f = explode($operator, $filter);
                                          if (count($f) == 2) {
                                              $tvName = $modx->quote($f[0]);
                                              if (is_numeric($f[1]) && !in_array($sqlOperator, array('LIKE', 'NOT LIKE'))) {
                                                  $tvValue = $f[1];
                                                  if ($f[1] == (integer)$f[1]) {
                                                      $tvValueField = "CAST({$tvValueField} AS SIGNED INTEGER)";
                                                      $tvDefaultField = "CAST({$tvDefaultField} AS SIGNED INTEGER)";
                                                  } else {
                                                      $tvValueField = "CAST({$tvValueField} AS DECIMAL)";
                                                      $tvDefaultField = "CAST({$tvDefaultField} AS DECIMAL)";
                                                  }
                                              } else {
                                                  $tvValue = $modx->quote($f[1]);
                                              }
                                              if ($multiple) {
                                                  $filterGroup[] = "(EXISTS (SELECT 1 FROM {$tmplVarResourceTbl} tvr JOIN {$tmplVarTbl} tv ON {$tvValueField} {$sqlOperator} {$tvValue} AND tv.name = {$tvName} AND tv.id = tvr.tmplvarid WHERE tvr.contentid = modResource.id) " .
                                                      "OR EXISTS (SELECT 1 FROM {$tmplVarTbl} tv WHERE tv.name = {$tvName} AND {$tvDefaultField} {$sqlOperator} {$tvValue} AND tv.id NOT IN (SELECT tmplvarid FROM {$tmplVarResourceTbl} WHERE contentid = modResource.id)) " .
                                                      ")";
                                              } else {
                                                  $filterGroup = "(EXISTS (SELECT 1 FROM {$tmplVarResourceTbl} tvr JOIN {$tmplVarTbl} tv ON {$tvValueField} {$sqlOperator} {$tvValue} AND tv.name = {$tvName} AND tv.id = tvr.tmplvarid WHERE tvr.contentid = modResource.id) " .
                                                      "OR EXISTS (SELECT 1 FROM {$tmplVarTbl} tv WHERE tv.name = {$tvName} AND {$tvDefaultField} {$sqlOperator} {$tvValue} AND tv.id NOT IN (SELECT tmplvarid FROM {$tmplVarResourceTbl} WHERE contentid = modResource.id)) " .
                                                      ")";
                                              }
                                          } elseif (count($f) == 1) {
                                              $tvValue = $modx->quote($f[0]);
                                              if ($multiple) {
                                                  $filterGroup[] = "EXISTS (SELECT 1 FROM {$tmplVarResourceTbl} tvr JOIN {$tmplVarTbl} tv ON {$tvValueField} {$sqlOperator} {$tvValue} AND tv.id = tvr.tmplvarid WHERE tvr.contentid = modResource.id)";
                                              } else {
                                                  $filterGroup = "EXISTS (SELECT 1 FROM {$tmplVarResourceTbl} tvr JOIN {$tmplVarTbl} tv ON {$tvValueField} {$sqlOperator} {$tvValue} AND tv.id = tvr.tmplvarid WHERE tvr.contentid = modResource.id)";
                                              }
                                          }
                                      }
                                      $conditions[] = $filterGroup;
                                  }
                                  if (!empty($conditions)) {
                                      $firstGroup = true;
                                      foreach ($conditions as $cGroup => $c) {
                                          if (is_array($c)) {
                                              $first = true;
                                              foreach ($c as $cond) {
                                                  if ($first && !$firstGroup) {
                                                      $criteria->condition($criteria->query['where'][0][1], $cond, xPDOQuery::SQL_OR, null, $cGroup);
                                                  } else {
                                                      $criteria->condition($criteria->query['where'][0][1], $cond, xPDOQuery::SQL_AND, null, $cGroup);
                                                  }
                                                  $first = false;
                                              }
                                          } else {
                                              $criteria->condition($criteria->query['where'][0][1], $c, $firstGroup ? xPDOQuery::SQL_AND : xPDOQuery::SQL_OR, null, $cGroup);
                                          }
                                          $firstGroup = false;
                                      }
                                  }
                      
                                  return true;
                      
                              }
                      
                          }
                      }
                      
                      
                      $c = $modx->newQuery('modResource');
                      $c->where(array('published' => 1,
                          'template' => 4,
                          'deleted' => 0
                      ));
                      
                      $filter = array();
                       
                      if (isset($_POST["jaartal"]) && $_POST["jaartal"] != '0') {
                          $filter[] = 'startjaar===' . $_POST["jaartal"] ;
                      }
                       
                      if (isset($_POST["categorie"]) && $_POST["categorie"] != '0') {
                          $filter[] = 'categorie===' . $_POST["categorie"] ;
                      }
                      
                      if (count($filter)>0){
                          tvFilters(implode(',',$filter), $c);
                      }
                      
                      $docArray = $modx->getCollection('modResource', $c);
                      
                      
                        -------------------------------

                        you can buy me a beer, if you like MIGX

                        http://webcmsolutions.de/migx.html

                        Thanks!