We launched new forums in March 2019—join us there. In a hurry for help with your website? Get Help Now!
    • 3749
    • 24,544 Posts
    OK I get it now, in fact I almost never use output modifiers myself.

    Have you tried using toArray() and getChunk()? They are generally quite fast.
      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
      • 36782
      • 109 Posts
      @Bruno17
      That's an interesting idea, maybe I'll try it out. I have done something similar with Template Vars before, to try to get around the speed penalty of TVs in getResources calls. So I know this kind of thing will potentially work in getResources template chunks. Thanks for the suggestion.

      @BobRay
      :) Yeah, it was your advice which got me trying to avoid output modifiers. Thanks for that!
      I'll try toArray() with getChunk(). I bet I could do
      getChunk('myChunk', toArray($myResource)); for instances where I want everything returned. And it looks like toArray makes placeholders too...?
        • 4172
        • 5,888 Posts
        here's the modified If snippet 'getChunkIf' (experimental) which seems to work so far:

        /**
         * getChunkIf
         *
         * Copyright 2009-2010 by Jason Coward <[email protected]> and Shaun McCormick
         * <[email protected]>
         *
         * getChunkIf is free software; you can redistribute it and/or modify it under the terms
         * of the GNU General Public License as published by the Free Software
         * Foundation; either version 2 of the License, or (at your option) any later
         * version.
         *
         * If is distributed in the hope that it will be useful, but WITHOUT ANY
         * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
         * A PARTICULAR PURPOSE. See the GNU General Public License for more details.
         *
         * You should have received a copy of the GNU General Public License along with
         * If; if not, write to the Free Software Foundation, Inc., 59 Temple Place,
         * Suite 330, Boston, MA 02111-1307 USA
         *
         * @package getChunkIf
         */
        /**
         * Simple If (conditional) snippet
         *
         * @package getChunkIf
         */
        if (!empty($debug)) {
            print_r($scriptProperties);
            if (!empty($die)) die();
        }
        if (!empty($scriptProperties['placeholder'])){
            $subject = '[[+'.$scriptProperties['placeholder'].']]';
        }
        
        $modx->parser->processElementTags('',$subject,true,true);
        
        $output = '';
        $operator = !empty($operator) ? $operator : '';
        $operand = !isset($operand) ? '' : $operand;
        if (isset($subject)) {
            if (!empty($operator)) {
                $operator = strtolower($operator);
                switch ($operator) {
                    case '!=':
                    case 'neq':
                    case 'not':
                    case 'isnot':
                    case 'isnt':
                    case 'unequal':
                    case 'notequal':
                        $outputchunk = (($subject != $operand) ? $thenchunk : (isset($elsechunk) ? $elsechunk : ''));
                        break;
                    case '<':
                    case 'lt':
                    case 'less':
                    case 'lessthan':
                        $outputchunk = (($subject < $operand) ? $thenchunk : (isset($elsechunk) ? $elsechunk : ''));
                        break;
                    case '>':
                    case 'gt':
                    case 'greater':
                    case 'greaterthan':
                        $outputchunk = (($subject > $operand) ? $thenchunk : (isset($elsechunk) ? $elsechunk : ''));
                        break;
                    case '<=':
                    case 'lte':
                    case 'lessthanequals':
                    case 'lessthanorequalto':
                        $outputchunk = (($subject <= $operand) ? $thenchunk : (isset($elsechunk) ? $elsechunk : ''));
                        break;
                    case '>=':
                    case 'gte':
                    case 'greaterthanequals':
                    case 'greaterthanequalto':
                        $outputchunk = (($subject >= $operand) ? $thenchunk : (isset($elsechunk) ? $elsechunk : ''));
                        break;
                    case 'isempty':
                    case 'empty':
                        $outputchunk = empty($subject) ? $thenchunk : (isset($elsechunk) ? $elsechunk : '');
                        break;
                    case '!empty':
                    case 'notempty':
                    case 'isnotempty':
                        $outputchunk = !empty($subject) && $subject != '' ? $thenchunk : (isset($elsechunk) ? $elsechunk : '');
                        break;
                    case 'isnull':
                    case 'null':
                        $outputchunk = $subject == null || strtolower($subject) == 'null' ? $thenchunk : (isset($elsechunk) ? $else : '');
                        break;
                    case 'inarray':
                    case 'in_array':
                    case 'ia':
                        $operand = explode(',',$operand);
                        $outputchunk = in_array($subject,$operand) ? $thenchunk : (isset($elsechunk) ? $elsechunk : '');
                        break;
                    case '==':
                    case '=':
                    case 'eq':
                    case 'is':
                    case 'equal':
                    case 'equals':
                    case 'equalto':
                    default:
                        $outputchunk = (($subject == $operand) ? $thenchunk : (isset($elsechunk) ? $elsechunk : ''));
                        break;
                }
            }
        }
        if (!empty($debug)) { var_dump($output); }
        unset($subject);
        //echo $outputchunk;
        //print_r($scriptProperties);
        return $modx->getChunk($outputchunk);
        
        [ed. note: Bruno17 last edited this post 14 years, 10 months ago.]
          -------------------------------

          you can buy me a beer, if you like MIGX

          http://webcmsolutions.de/migx.html

          Thanks!
          • 36782
          • 109 Posts
          That's great! Not just as a useful snippet, but as a learning tool for me, too. Thanks very much for posting that. I might try trimming it down for more specific situations where not all of the logic would be used.

          Brilliant smiley
            • 9102 ☆ A M B ☆
            • 318 Posts
            OK, you're absolutely right unsub777, if uncached performance is a limitation then it may very well be worth the time to write your own snippets for this. getResources is a great tool, but it can get pretty slow when you have snippet calls inside your templates. Even with plenty of horsepower, I have pages that take about 5 sec to render uncached.

            As for how to do conditional templating more efficiently with getResources, interestingly, we just had a discussion almost identical to this in this thread: https://forums.modx.com/thread/?thread=72492&page=1

            Bruno17, I think you may find that your snippet runs into trouble when the output chunk is a getResources template with placeholders for resource fields. The values of the placeholders won't be passed into the chunk, you have to get them again and pass them into the chunk as an array of properties.

            I posted some code to do that, but in the end I decided it would be a lot more efficient to just do the conditional logic inside of getResrouces itself. That way you don't have to call another snippet in the template, which seems to have some overhead cost, and you don't have to get the resource fields again because getResources already has them, all you have to do is change the chunk being used as a template.

            So I forked getResources and put in a pull request to Jason to include code very similar to your getChunkIf snippet (my version takes a JSON array of operand-chunk pairs in case you have lots of different conditions you need to template for, but otherwise it's pretty much the same). My fork is here: https://github.com/freejung/getResources

            unsub777, you might give my version of getResources a try and see if it performs better than putting a snippet call in the template -- but ultimately you're right, you're probably always going to get better performance with code that's specific to your exact setup than with a general-purpose tool like getResources.
              • 9102 ☆ A M B ☆
              • 318 Posts
              Never mind, I just realized that for this purpose my version of getResources won't work, there are too many conditions. I need to extend it to support more complicated logic -- but even then it wouldn't work because you're not talking about just selecting one chunk to use as a template, you're talking about stringing several chunks together.

              Never mind. The way you're already doing it is probably the best way to go.

              The getChunkIf snippet would work fine for this case if you pass the subject into the output chunk as a property, like this:

              return $modx->getChunk($outputchunk, array($placeholder => $subject));
              


              At least, I think that would work, I haven't tested it. That is, it will work if this one placeholder (introtext in the example) is the only placeholder used in the output chunk. Otherwise you'll have to get the other placeholders and pass them in as well.
                • 9102 ☆ A M B ☆
                • 318 Posts
                Hmm... nope, Bruno17, I can't seem to get your snippet to work properly inside of a getResources template no matter what I do. To begin with, this code:
                if (!empty($scriptProperties['placeholder'])){
                    $subject = '[[+'.$modx->getPlaceholder($scriptProperties['placeholder']).']]';
                }
                 
                $modx->parser->processElementTags('',$subject,true,true);
                

                gives me an empty subject regardless of the value of introtext, presumably because you're actually wrapping the value of the introtext inside a tag and then parsing it. So I changed it to just:
                if (!empty($scriptProperties['placeholder'])){
                    $subject = $modx->getPlaceholder($scriptProperties['placeholder']);
                }
                


                That gives me the correct value of the subject, but only on the first iteration of getResources. On subsequent iterations, if I call getChunkIf cached then it always gives me the same value of subject. If I call it uncached, then subsequent values of subject are empty regardless of the actual value of introtext.

                I'm sorry, I'm confused, I can't seem to get it to work. There's something funky about the way placeholders are being handled on subsequent iterations of getResources.

                I'd be interested to get this working, because I think it would be a lot more efficient than my method that I posted in the other thread (referenced above), because you're taking the values of resource fields from the placeholders in the getResources template rather than getting them directly from the resource, which involves querying the resource again. Unfortunately doing it this way doesn't seem to work properly, and my way will probably perform so poorly that it will still break unsub777's host. And doing it inside getResources itself also won't work because of needing to string several chunks together.

                So... I give up. I think the best way to do this is the way you're already doing it, unsub777.

                Maybe I'll start doing it that way too.
                  • 4172
                  • 5,888 Posts
                  @freeyoung:

                  its working for me without changes (on a 2.1.4 installation) with this call:

                  <h3>[[+pagetitle]]</h3>
                  [[getChunkIf? &placeholder=`introtext` &operator=`!empty` &thenchunk=`introchunk` &elsechunk=`contentchunk` &resid=`[[+id]]`]]
                  


                  cached call and with a resid-property (to get a unique snippet-tag for each row)
                    -------------------------------

                    you can buy me a beer, if you like MIGX

                    http://webcmsolutions.de/migx.html

                    Thanks!
                    • 9102 ☆ A M B ☆
                    • 318 Posts
                    What does the resid property do within the snippet?
                      • 4172
                      • 5,888 Posts
                      it does nothing in the snippet.
                      Its only to get a unique snippet-tag for each row, because of caching.
                      When you call the same snippet more than once with same properties on one page-load you will allways get the same result as in the first snippet-call.

                      you need only change one property (here
                      resid=`[[+id]]`
                      ) for each call. Then the snippet is processed new for each snippet-call.

                      I think, its done in this lines in modelement.class.php function process:

                              if ($this->isCacheable() && isset ($this->xpdo->elementCache[$this->_tag])) {
                                  $this->_output = $this->xpdo->elementCache[$this->_tag];
                                  $this->_processed = true;
                              }
                      

                        -------------------------------

                        you can buy me a beer, if you like MIGX

                        http://webcmsolutions.de/migx.html

                        Thanks!