We launched new forums in March 2019—join us there. In a hurry for help with your website? Get Help Now!
    • 39932
    • 483 Posts
    Fuzzical Logic Reply #1, 14 years ago
    Snippets are arguably the most used Elements in MODx. Many packages come with multiple Snippets and most need at least one Snippet to even function. The MODx parser allows you to do a lot of neat things when calling a Snippet, for instance, setting a script property that isn't necessarily listed as a Property. This kind of dynamic calling behavior is truly awesome, as it fires silently... If the property is not used, its not a big deal, but if it is used, this can be good or bad depending on the user need. This is only one of the considerations you must always take into account when writing Snippets that may be used by others.

    As a Snippet writer, it is up to you to make sure that your Snippet works well for others. This is especially true if you are submitting it as a MODx Extra. Here are some tips that can help ensure a great experience for your Snippet users:


    • Initialize any Properties that are necessary.
    • "Error Check" all values and exit quickly. Do not continue to process if you know early that there will be no output.
    • Allow users to send the results to a Placeholder.
    • If you have a value that is used between multiple Snippets, set it to a configurable Placeholder, as well.
    • Block your code to avoid worthless execution. This will save processing and memory, and may have significant benefits.
    • When using xPDO, get as much (and only) information as you need. In other words, use $q->select(). Don't get the entire 'modResource' when all you need is an 'id'.
    • When using xPDO, try to use as few queries as possible. This is subjective; sometimes, many tiny queries can offset one large one.
    • Consider a &debug property or using the System Setting provided with Revo. This can avoid a lot of misspent time trying to figure out why something is not working. If you blocked your code and did some value checking, the process load will be nil.
    • Do not rely on the logs for debug text during development (live sites are another story). Unless you or the user sets the log level, your debug text may not reach the user's eyes. Considering the above tip, an output that states "Chunk "thisChuk" was not found" will be much easier to resolve as a typo, than having to run it multiple times then set the log level and then try and find the log message. Most debug text is needed during development rather than on production, anyway. Additionally, overriding the log level is generally bad practice as the admin should determine what is acceptable for the site log.
    • When you document, let the user know if you are passing scriptProperties or not to subsequent Chunks and Snippets. This will tell them exactly how to use your Snippet.
    • Remember that $modx is a xPDO object. Even grabbing something as simple as a System Setting is an xPDO query. It may be faster (in general) but do it too many times and you can still affect your user's load negatively.
    • Create a Default Property Set for all Snippets you will give away. This helps to automatically initialize scriptProperties which can save you code for your "less important" Properties. All necessary Properties should be initialized in the code, in case the default property set is messed up.

    Always remember, when you are writing a Snippet, you are writing software. It may be small platform specific software, but it is software, nonetheless. There are expectations and requirements, and these are set by many factors that are in your direct control. These tips help to provide guidelines (not requirements) about how those expectations can be met reliably

    A Possible Suggestion for future Snippets: (Certainly open for discussion)... Using "tpl" may be the standard, but it is a poor standard that no longer applies to the Revo terminology. While it may provide familiarity for those coming from past versions of MODx, this is confusing to many new users who are not code literate. Tpl is short for template, not chunks. When adopting a terminology, adopt it fully or else new users will have difficulty (many have already and will continue to until a statement is made). A less confusing alternative is "chunk", "toChunk", "rowChunk", "outerChunk", etc. If the concern is keystrokes, consider "chk", but this is just as ambiguous as "tpl", IMHO. Making the conversion is as simple as a statement in the code (if (!empty($tpl)) $toChunk = $tpl;) This can allow for the standards change will providing backward compatibility for future versions of the Snippet. [ed. note: fuzzicallogic last edited this post 14 years ago.]
      Website: Extended Dialog Development Blog: on Extended Dialog
      Add-ons: AJAX Revolution, RO.IDEs Editor & Framework (in works) Utilities: Plugin Compatibility List
      Tutorials: Create Cross-Context Resources, Cross-Context AJAX Login, Template-Based Actions, Remove Extensions from URLs

      Failure is just another word for saying you didn't want to try. "It can't be done" means "I don't know how".
      • 39932
      • 483 Posts
      Fuzzical Logic Reply #2, 14 years ago
      Supplemental Post: Sample Snippet

      This is a sample Snippet using the above techniques. It is in active use on my very complex site, but incurs very little load and is highly useful whether I am developing or not. While there are a couple of bad practices (using HTML from directly within a Snippet), in these cases, it seems unavoidable.

      <?php
      // Allows for a specified User. 
      // User in this context is a User's personal Blog which uses its ID as its alias. 
      // This function may be called from any place, but just in case, 
      // we will use the results of the current User if the param is suspect.
          $forUser = !empty($forUser)
              ? $forUser                              // The specified User
              : $modx->resource->get('template') == 2
                  ? $modx->resource->get('alias') // Use the Alias
                  :  $modx->user->get('id');       // Fallback to User ID
      
      // Initialize the rest of the necessary properties
          $boxChunk = !empty($boxChunk)
              ? $boxChunk
              : 'toLinkList';
          $rowChunk = !empty($rowChunk)
              ? $rowChunk
              : 'toBlogLink';
          $limit = empty($limit) ? 10 : $limit;
      
      // This is initialized with the System Setting, if it is not provided.
          $debug = (!empty($debug))
              ? $debug
              : $modx->getOption('debug');
      
      // Single xPDO Query
          $q = $modx->newQuery(
              'modResource'
          );
          $q->innerJoin('modTemplateVarResource','TemplateVarResources');
      // This limits it to a Context, making the result list smaller.
          $q->where(array(
                  'modResource.context_key'=>projects,
                  'modResource.template'=>15,
                  'modResource.published'=>1,
                  'TemplateVarResources.tmplvarid'=>5
          ));
      // Account for comma-delimited lists where id is first, last or only entry...
          $values[] = array('TemplateVarResources.value'=>$forUser);
          $values[] = array('OR:TemplateVarResources.value:LIKE' => '%,'.$forUser.'%');
          $values[] = array('OR:TemplateVarResources.value:LIKE' => '%'.$forUser.',%');
          $q->andCondition($values, null, 1);
      // This makes the result set even smaller, and the query return much faster.
          $q->select(array('id', 'pagetitle', 'introtext'));
          $q->limit($limit);
          $list = $modx->getCollection('modResource', $q);
          if (!empty($debug))
              $output .= 'Query complete: attempting to output results';
      
      // We only work if we have a list.
          if (!empty($list))
          {   foreach ($list as $key => $project)
              {   if (!empty($project))
                  {   $members = $project->getTVValue('Contributors');
                      if (!empty($members))
                      {   $members = explode(',', $members);
                          foreach($members as $key => $member)
                          {//Accounts for *# or #* results.
                              if (trim($member) == $forUser)
                              {   $output .= '<li>'
                                          . $modx->getChunk(
                                              $rowChunk, 
                                              array(
                                                  'id'=>$project->get('id'),
                                                  'text'=>$project->get('pagetitle'),
                                                  'desc'=>$project->get('introtext')
                                              )
                                          )
                                          .'</li>';
                              // We only care if it matches once.
                                  break;                        
                              }
                              elseif (!empty($debug))
                                  $output .= '<li>Does not match:' . $member . '</li>'
                          }
                      }
                      elseif (!empty($debug))
                          $output .= '<li>Project has no members.</li>';        
                  }
                  elseif (!empty($debug))
                      $output .= '<li>Query included an empty result. Consider revising</li>';
              }
              $output = $modx->getChunk($boxChunk, array('items'=>$output));
          }
          elseif (!empty($debug))
              $output = 'There were no results to list for id:'.$forUser;
      
      // If Placeholder is requested
          if (empty($toPlaceholder))
              return $output;
          else 
              $modx->setPlaceholder($toPlaceholder, $output);
      // Only return "sure" output. Better than mangling a User's page
          return '';
      
      [ed. note: fuzzicallogic last edited this post 14 years ago.]
        Website: Extended Dialog Development Blog: on Extended Dialog
        Add-ons: AJAX Revolution, RO.IDEs Editor & Framework (in works) Utilities: Plugin Compatibility List
        Tutorials: Create Cross-Context Resources, Cross-Context AJAX Login, Template-Based Actions, Remove Extensions from URLs

        Failure is just another word for saying you didn't want to try. "It can't be done" means "I don't know how".
        • 28042 ☆ A M B ☆
        • 24,524 Posts
        The only meaning for "tpl" is that it is a mini-template for use by a snippet when formatting the snippet's output. The abbreviated form is used to differentiate these from the main site "Templates". A tpl can be a chunk, a file, or direct input using @CODE syntax. Actually it could be just about anything the snippet writer wants it to be; the point is that while it is, in fact, a template, it is not the Template!
          Studying MODX in the desert - http://sottwell.com
          Tips and Tricks from the MODX Forums and Slack Channels - http://modxcookbook.com
          Join the Slack Community - http://modx.org
          • 39932
          • 483 Posts
          Fuzzical Logic Reply #4, 14 years ago
          Agreed. That's kind of my point. It's ambiguous... and may be unavoidably so in some circumstances. But for many Snippets, it is often a chunk of output (the results of a Snippet, an actual chunk, passed chunks of HTML). Making a distinction between Template and template is often unclear for newer users. If the only difference in the term is a capital letter and a lowercase letter, then we might want to realign the term.

          I'm certainly not saying it is an imperative, but this is a common practice that is not mentioned (only implied) in the documentation and introduction to new users (Hence, "until a statement is made" in my above post). Given that its never stated that template and Template are not the same thing, it is a natural assumption for newer users to assume that they are...

          Note: I updated the suggestion to lowercase template, instead, as this was more to the point and could be misleading for further discussion. [ed. note: fuzzicallogic last edited this post 14 years ago.]
            Website: Extended Dialog Development Blog: on Extended Dialog
            Add-ons: AJAX Revolution, RO.IDEs Editor & Framework (in works) Utilities: Plugin Compatibility List
            Tutorials: Create Cross-Context Resources, Cross-Context AJAX Login, Template-Based Actions, Remove Extensions from URLs

            Failure is just another word for saying you didn't want to try. "It can't be done" means "I don't know how".
            • 28042 ☆ A M B ☆
            • 24,524 Posts
            tpl. Not template (lower case). tpl (abbreviation) is used to differentiate from the main site templates. I capitalized Template to make it extra-clear we were referring to the site template elements.

            So if you see tpl, it's referring to a snippet's output formatting structure, whatever the origin of it may be. If you see template, it's referring to a site template element.
              Studying MODX in the desert - http://sottwell.com
              Tips and Tricks from the MODX Forums and Slack Channels - http://modxcookbook.com
              Join the Slack Community - http://modx.org
              • 39932
              • 483 Posts
              Fuzzical Logic Reply #6, 14 years ago
              My point is that tpl is short for template which is not far from Template. My argument is that many people tell me that MODx is designed so that users do not have to be technical in order to use it. MODx accomplishes this well. The subtle distinction between "tpl" which is a "mini-template" and Template is arguably too subtle. I've had to teach many newer users (who are frustrated trying to get the terminology straight) that tpl and Template are not the same thing. It's not that new users are simple, its that the terminology and usage is in conflict with regard to that specific term.

              I would consider what its like to move from a more strict environment with strong terminology, to a flexible environment where the terminology is fairly consistent, but can be loose at times. For us technical people, such changes are incredibly easy to make, but for some this is not an easy change and the only thing that boosts their confidence and will is that they know when they see a term, they'll know exactly what it is.

              Whenever a widely used platform changes the way a terminology is used, its generally better if it is consistent across the board. I argue that a change to that one standard would reinforce this and make the platform more accessible for a wider set of users. Certainly, this would and should not be immediate, and not for all circumstances, but the suggestion is for general application.
                Website: Extended Dialog Development Blog: on Extended Dialog
                Add-ons: AJAX Revolution, RO.IDEs Editor & Framework (in works) Utilities: Plugin Compatibility List
                Tutorials: Create Cross-Context Resources, Cross-Context AJAX Login, Template-Based Actions, Remove Extensions from URLs

                Failure is just another word for saying you didn't want to try. "It can't be done" means "I don't know how".
                • 3749
                • 24,544 Posts
                We fought about this during the MODX terminology wars. wink

                We somewhat settled on calling them "Tpl Chunks" and that's all I've ever called them. It's better than "tpls" because "Tpl" in this usage is an adjective that tells what kind of *chunks* they are. They're definitely a special kind of chunk and a whole lot of extras use &tpl* properties to reference them.

                Susan will argue with me (and did then) because they're not always chunks, and she's right. IMO, though, by the time a user needs to know that, they already know what they are, and it doesn't hurt to think of the other forms as stand-ins for a chunk. Almost all extras will look for a chunk by default if you specify just a name in an &tpl* property.

                There's no ideal solution that I know of, because calling them Templates is out of the question and no other term describes them adequately other than "tpl" or "Tpl Chunk." You're right that those terms cause problems for new MODX users, but IMO, not using them causes worse problems.


                ------------------------------------------------------------------------------------------
                PLEASE, PLEASE specify the version of MODX you are using.
                MODX info for everyone: http://bobsguides.com/modx.html
                  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
                  • 39932
                  • 483 Posts
                  Fuzzical Logic Reply #8, 14 years ago
                  Well, personally, I think "Chunk" is way closer. As a Chunk is incomplete markup. A snippet nearly always produces chunk-type HTML or other code. Its not a far stretch. (Until a firm stand is made, I will be supporting both as I currently do.) @CODE normally results in output similar to a chunk. So, no, its not a Chunk, but it is much closer.

                  Maybe a viable alternative is a neutral term... like "out" which accounts for both (and others) but does not take a stand. I think "out" is too ambiguous, but for the sake of pushing forward, I think it should at least be mentioned.

                  but IMO, not using them causes worse problems.

                  Not using a standard term would definitely cause problems. In total agreement there. The standard now is firmly established and would take debate and exercise to change. I'm arguing for slow change, but more important to me is to have a beneficial discussion as to the benefits/detriments of the behavior (long-term) and potentially some alternatives.

                  Clarification: My concern is the "tpl" is geek-speak. I love geek-speak, but I'm a geek. Non-geeks fail to understand or accept most of geek-speak and that's just a simple fact. Geeks have become more and more integrated into society as a standard due to their self-acceptance that a crazy love of acronyms and abbreviations is not normal. By changing this behavior when (and only when) it will be exposed to society, we've gained a large measure of admiration and respect, when geeks used to be ridiculed and despised for their eccentric love of efficiency.

                  MODx is exposed, and specifically marketed to non-geeks, and we, as geeks, can make the community stronger, or we can fight about it and slow the acceptance and growth of the platform. This isn't a MODx Team problem, this is a MODx geek problem as we're the ones who teach, make all of the Snippets, write a lot of the documentation, etc, etc...
                    Website: Extended Dialog Development Blog: on Extended Dialog
                    Add-ons: AJAX Revolution, RO.IDEs Editor & Framework (in works) Utilities: Plugin Compatibility List
                    Tutorials: Create Cross-Context Resources, Cross-Context AJAX Login, Template-Based Actions, Remove Extensions from URLs

                    Failure is just another word for saying you didn't want to try. "It can't be done" means "I don't know how".
                    • 28042 ☆ A M B ☆
                    • 24,524 Posts
                    Actually I was quite happy calling them mini-templates.
                      Studying MODX in the desert - http://sottwell.com
                      Tips and Tricks from the MODX Forums and Slack Channels - http://modxcookbook.com
                      Join the Slack Community - http://modx.org
                      • 39932
                      • 483 Posts
                      Fuzzical Logic Reply #10, 14 years ago
                      Geek :-p [ed. note: fuzzicallogic last edited this post 14 years ago.]
                        Website: Extended Dialog Development Blog: on Extended Dialog
                        Add-ons: AJAX Revolution, RO.IDEs Editor & Framework (in works) Utilities: Plugin Compatibility List
                        Tutorials: Create Cross-Context Resources, Cross-Context AJAX Login, Template-Based Actions, Remove Extensions from URLs

                        Failure is just another word for saying you didn't want to try. "It can't be done" means "I don't know how".