We launched new forums in March 2019—join us there. In a hurry for help with your website? Get Help Now!
    • 9207 ☆ A M B ☆
    • 2,475 Posts
    I’d like to pull up a template using MODx Revolution... what’s the object that should be used?

    AND... is this even possible? I’d like to parse everything in the template (e.g. the Chunks and embedded Snippets), but I’d like to set what the Template Variables are (e.g. [[*content[[) from WITHIN my Snippet. This is to enable me to use a standard MODx template to format custom content that I’m retrieving via a Snippet.

    I feel like I’m breaking new ground... but... this has surely been done before, no?
      • 3749
      • 24,544 Posts
      The quickest way to get a template is:

      $modx->getObject(’modTemplate’,$id);

      (where $id is the ID of the template).

      I think you may be confused about what’s where and what it’s called, though. You probably know almost all of this, but it might be useful for others starting out in Revolution.

      First off, [[*content]] isn’t a Template Variable, it’s a Resource Field (though in Evo, these are often erroneously called TVs). TVs are the ones you create yourself. In Revo, it’s more important not to call Resource Fields TVs because working with actual TVs in snippet and plugin code is a very different process, even though you display them with the same tag you use for Resource Fields.

      Secondly, the Resource Fields aren’t tied to the template in any way, they’re members of the resource object itself. There are various places to see the full list of them, but using this tiny snippet is the most fun (IMHO):

      return '<pre>' . print_r($modx->resource->toArray(), true) . '</pre>';


      To break it down, $modx->resource is always the current page being viewed. The toArray() member method will turn all the fields of any MODx object into an associative array of keys and values (try the above code with $modx->user instead of $modx->resource).

      To actually use the Resource Content fields, you call the resource object’s get() method with the name of the field:

      $contentField = $modx->resource->get('content');


      This works with resources other than the current one, too, as long as you get them first with something like this:

      $resource =& $modx->getObject('modResource'$id);
      $contentField = $resource->get('content');


      You can also get a resource by pagetitle (or any other field) like this:
      $resource =& $modx->getObject('modResource',array('pagetitle'=>'MyPage'));


      I hope at least some of that is relevant to your question. tongue

      Back to your original question. I’m not completely clear on what you’re trying to do and why, but I wonder if you couldn’t just duplicate the template you want and replace the [[*content]] tag with your snippet tag. That way, MODx would handle everything but processing your custom content section, which you’d do in your snippet.

        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
        • 9207 ☆ A M B ☆
        • 2,475 Posts
        Thank you, Bob, that was very informative!

        The reason I want to handle template parsing including all of its chunks and snippets is a good one, and it involves dealing with custom content. For a long time, I’ve been working with custom data models that existed separately from MODx. Let’s say it’s business req’s that certain data lives in a foreign database, but the reason could also be to address the inefficient table joins that occur when assembling multiple Template Variables.

        Whatever the reason, we end up having a row in a foreign database table that we want to view as a web page, and that includes placing some of that content into the <head>, maybe some other bit of the custom content into the <h1>, maybe something else goes at the bottom of the page... in short, when the custom content is viewed as its own page, I need to access the entire page, not just the [[*content]] placeholder. Does that make sense?

        In the past (Evo), I would put multiple Snippet calls all over the page, everywhere I needed data from that custom database -- the first time the Snippet ran, it would cache the result somewhere in the $modx object, then subsequent instances of the Snippet would simply retrieve the cached data instead of hitting the database again. That approach works, but the Snippet calls got really messy. The other solution I came up with was to use a Chunk that was in fact an entire web page, and use that to format Snippet output... but that duplicated a lot of work that was already in existing templates. Still with me?

        So, I figured it would be a better a solution to tie in directly to an existing template. First, I created a dedicated page meant to display rows of custom content based off of a $_GET parameter, e.g. /my/page?custom_id=123 and that page would contain a single instance of my Snippet in the content area. In the manager, I’d set this page to use a blank template (i.e. one with ONLY [[*content]]), and I’d rely on the Snippet to choose a separate template to output the entire HTML body (e.g. imagine something like this [[!accessCustomData? &use_template=`4`]] ). I could use a Chunk to format the Snippet output, but again, I already have templates used elsewhere in the site that I’d prefer to tie into -- this is especially true when it comes to recreating dynamic portions of the pages, such as menus. I could "print" the output of Wayfinder and put the resulting HTML into my Chunk, but you can see where that goes... as soon as a page is added or unpublished, etc. I have to update my Chunk.

        Does this situation make sense? I hope it does... so back to the matter at hand, I’ve been able to load up a Template in my Snippet, no problem... and I can retrieve my custom data from my external database... but... how do I render the current page and manually feed it Template Variables -- these would NOT be "real" template variables, but rather the data from my custom content.

        Your guidance is always appreciated smiley
          • 28042 ☆ A M B ☆
          • 24,524 Posts
          You could handle this with a resource with no template, using placeholders in your snippet like Ditto and Wayfinder. Include the PHx class and PHx processing in your snippet like Ditto and Jot do, and you’d have a very powerful custom data presentation snippet (which actually is exactly what Jot is).
            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
            • 9207 ☆ A M B ☆
            • 2,475 Posts
            Thanks Susan... but that’s exactly what I’m trying to avoid: my chunks end up mimicking my templates to the Nth degree, and the chunk-approach doesn’t allow for me to tie into the built-in MODx parsing.
              • 3749
              • 24,544 Posts
              Why not a single MODx template with placeholders for all the stuff you want to inject and one snippet to pull from the DB and set the placeholders?
                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
                • 9207 ☆ A M B ☆
                • 2,475 Posts
                EXACTLY!!! How?
                  • 34017
                  • 898 Posts
                  Here’s what I do.

                  <?php
                  //This is a onpagenotfound plugin. If the url is sitename.com/custom/anything/and/everything... modx sends forward my custom page
                  
                  $e = &$modx->Event;
                  
                  if( $e->name != 'OnPageNotFound') {
                      return;
                  }
                  
                  $custom_page = 70;
                  
                  $uri = explode('/', $_SERVER['REQUEST_URI']);
                  
                  if( isset($uri[1]) && $uri[1] == 'custom' ) {
                      $modx->sendForward($custom_page);
                  }
                  


                  Then on modx page 70, I have my template with the get data snippet in it.

                  I do 2 things:
                  1. Load the base template from a file
                  2. Where the content goes, run the data snippet ( I do this because i use Twig for my snippet templating engine)
                  <?php
                  
                  $tpl_defaults = array(
                      'path'  => '_/site/template/',
                      'page'  => 'default.tpl',
                      );
                  
                  $config = array_merge($tpl_defaults, $modx->event->params);
                  
                  foreach($config as $key => $value) {
                      $modx->setPlaceholder('tpl.'.$key, $value); 
                  }
                  
                  //Custom Stuff here
                  $custom_prefix = 'flexible';
                  $results = db->retrieve('kris mom');
                  if( ! $results ) {
                    $modx->setPlaceholder($custom_prefix'.no_results', '1');
                  } else {
                    foreach($results as $key => $value) {
                      $modx->setPlaceholder($custom_prefix.'.'.$key, $value);
                    }
                  }
                  
                  //Now all of your custom stuff is set to [+flexible.key+] so you can use input/output snippets, phx, etc. It's globally loaded for this page now
                  
                  $tpl = $modx->config['base_path'].$config['path'].$config['page'];
                  
                  if( !is_readable($tpl)) {
                      echo "{$config['page']} is not readable";
                      return; }
                  
                  //Now just load that html and let modx parse away
                  include $tpl;
                  
                  /*
                  Edit. In this page you could do anything. For example, you could grab the html template (or db template if you prefer). String replace each '[*' with '[+flexible.', then echo it. 
                  */
                  
                  


                  Very rough as you can tell. But this way you can load multiple friendly url/pages with one template. And you can set global placeholders for the page (which is what you originally wanted for H1, etc etc? no?)

                  Does that do it? Really just the second part.
                    Chuck the Trukk
                    ProWebscape.com :: Nashville-WebDesign.com
                    - - - - - - - -
                    What are TV's? Here's some info below.
                    http://modxcms.com/forums/index.php/topic,21081.msg159009.html#msg1590091
                    http://modxcms.com/forums/index.php/topic,14957.msg97008.html#msg97008
                    • 9207 ☆ A M B ☆
                    • 2,475 Posts
                    Thanks Chuck! What a wild Friday night we’re having! Yeah, that approach would do it in Evo wink but...

                    I made SOMETHING cool happen in Revo... but I’m not sure what. My page uses a blank template with only the [[*content]] placeholder, and in my page’s content, I’m calling my Snippet, which has something like this:

                    $virtual_page = $modx->newObject('modResource');
                    $virtual_page->set('template',5);
                    $virtual_page->set('pagetitle','My Virtual Page Title');
                    $virtual_page->set('content','Sample content here...');
                    return $virtual_page->process();


                    The key here is the process function. So SOMETHING happened... my #5 template was used to display the page, and that’s a REAL template -- and all the menu Snippets fired, all the Chunks in that Template were replaced, EVERYTHING. Very cool. But the other page properties did not get set.... the page title does NOT read ’My Virtual Page Title’, it’s still getting the page title from the page containing the Snippet. So setting the template like that somehow overrides the other attributes.

                    But this is heading in the right direction...
                      • 4172
                      • 5,888 Posts
                      this is something what seems to work:

                      <?php
                      
                      $myarray['pagetitle']='My Virtual Page Title';
                      $myarray['content']='Sample content here...';
                      
                      $toreplace='pagetitle,content';
                      
                      // get the Template:
                      $template=$modx->getObject('modTemplate','5');
                      
                      //replace placeholder tags where needed:
                      $toreplace = explode (',',$toreplace);
                      foreach ($toreplace as $repl){
                         $search[]='[[*'.$repl.']]';
                         $replace[]='[[+'.$repl.']]';
                      }
                      
                      $template=str_replace($search,$replace,$template->get('content'));
                      
                      //create a chunk with content from Template and process it.
                      $chunk = $modx->newObject('modChunk'); 
                      //$output = $chunk->process($myarray,$template);   
                      $chunk->setContent($template);
                      $output = $chunk->process($myarray);  
                      
                      return $output;
                      ?>
                        -------------------------------

                        you can buy me a beer, if you like MIGX

                        http://webcmsolutions.de/migx.html

                        Thanks!