We launched new forums in March 2019—join us there. In a hurry for help with your website? Get Help Now!
    • 42318
    • 25 Posts
    Hello

    I would like to know if it is possible to programmatically create a template variable and associate it with a template, using the modx api?

    Thanks!

    Tim
    • If you use runProcessor('tv/create', array(array(x))) you should be able to get it to work. http://rtfm.modx.com/revolution/2.x/developing-in-modx/advanced-development/using-runprocessor.

      Looking at the core/model/modx/processors/element/tv/create.class.php, it takes either an array of templates or a JSON string. So you would need to put an array of template IDs or a JSON string in the second parameter of the runProcessor function call. That second parameter is used to set templates, input options and output properties and the caption (if you don't specify a caption the name is used).
        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
        • 3749
        • 24,544 Posts
        Using runProcessor() is a better choice (because it will fire the appropriate System Events), but you can also do this (untested):

        /* Id of the template you want to attach it to */
        $templateId = 12;
        
        
        
        /* Make sure the TV doesn't already exist */
        $tv = $modx->getObject('modTemplateVar', array('name' => 'SomeTvName'));
        
        if (!$tv) {
            /* Create the TV */
            $tv = $modx->newObject('modTemplateVar');
            $tv->set('name', 'SomeTvName');
            $tv->set('default_text', 'SomeDefaultValue');
            // etc.
            if ($tv->save()) {
               /* Get the TV again so we can get its ID */
               $tv = $modx->getObject('modTemplateVar', array('name' => 'SomeTvName'));
               $tvId = $tv->get('id');
        
               /* Connect TV to Template */
               $tvt = $modx->newObject('modTemplateVarTemplate');
               $tvt->set('tmplvarid', $tvId);
               $tvt->set('template', $templateId);
               $tvt->save();
        
            }
        }


        If you want to set other fields of the TV, they're listed here: http://bobsguides.com/modx-object-quick-reference.html#modTemplateVar
          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
          • 42318
          • 25 Posts
          This is great.

          Thanks very much guys!

          So, after I have created the TV, I want to be able to save a value for the TV on a resource straight away.

          Do I need to clear the cache?

          I ran the code above you suggested Bob, than ran a $page->setTVValue..... on a resource, but it didn't update.

          So, I ran :

          $modx->cacheManager->refresh(array(
          'db' => array(),
          ));

          straight after creating the TV and before updating a resource with the TV.

          Is this the only way to do it, or is there a better way of being able to immediately update a TV value on a resource after creating the TV?

          Or is it better to use runProcessor as you suggested sottwell? - does the cache get cleared automatically when using this?

          Thanks again everyone!

          Tim
          • I don't think you can add a value all in one step with runProcessor('tv/create'...) when creating the TV, because that's for creating the TV itself. A TV's contentvalue gets saved when saving a resource. So using runProcessor('resource/update'...) might do the trick, and should automatically clear the cache as well. It takes an array of TV ids for updating.
              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
              • 3749
              • 24,544 Posts
              Updating a resource would work, but setting the TV value that way is a little clunky.

              Since you have the TV object, this single line would be easier and a little faster:

              $tv->setValue($resourceId, 'SomeValue');


              I think you would still have a cache issue because, IIRC, TV values for a resource are stored in the cached version of the resource, though you should only need to clear the resource cache. I could be wrong.

              If you use runProcessor() to create the TV, the TV object is in the return value, though you have to ask nicely for it. This is cribbed from creating a resource, but since all processors return the same type of object, it should work for TVs:

              $response = $modx->runProcessor('tv/create', etc');
              
              $tvObject = null;
              
              if ($response->isError()) {
                  if ($response->hasFieldErrors()) {
                      $fieldErrors = $response->getAllErrors();
                      $errorMessage = implode("\n", $fieldErrors);
                  } else {
                      $errorMessage = 'An error occurred: ' . $response->getMessage();
                  }
                  $modx->log(modX::LOG_LEVEL_ERROR, $errorMessage);
                  return '';
              
              } else {
                   $tvObject = $response->getObject();
                   $tvId = $object['id'];
              }
              
              if ($tvObject) {
                  $tvObject->setValue($resourceId, 'SomeValue');
              }
              
              

                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
                • 42318
                • 25 Posts
                Thanks everyone. I've got that working now.

                Using runprocesser worked great - for creating the TV and updating the resource.

                On a sidenote - does anyone know why you can't just pass an ID through to the $modx->runProcessor('resource/update'... ? I also had to pass a pagetitle, and a context? Surely an id is enough?

                Cheers

                Tim

                  • 3749
                  • 24,544 Posts
                  There is some stuff baked into the processor involving the uri and alias fields depending on the Friendly URLs System Setting. It needs the pagetitle for that.

                    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