Get TV Values -- The Fast Way

A look at various methods for getting TV values in MODX


In MODX snippets and plugins, you often need to get the value of a Template Variable for a given Resource. We'll look at three ways to do this, including a way that's much faster than the other two. Before getting to the code, though, we'll look at a couple of issues you need to think about when getting TV values.

Name or ID?

In many cases, you can get an object from the MODX database by ID or by "name." I put name in quotes because the "name" field isn't always called that. For resources, it's pagetitle, for templates it's templatename, and for categories, it's category. In any case, it's always faster to get the object by ID if possible, because the ID is the primary key in the database. Using the ID is also safer, because the name can change, but the ID never will.

In getting TV values, you can always use the TV's name, but using its ID will be faster and that's what we'll do in the examples in this article.

Rendered or Not?

TV values come in two flavors, rendered and raw. In the case of an @INHERIT TV, for example, the raw value might be @INHERIT, but the rendered value would be the value of the closest ancestor with a value for the TV. Similarly, for a date TV, the raw value would be a Unix timestamp, but the rendered value would be a human-readable date string. As you might guess, using the raw value is always faster since MODX has to do less processing before returning the value.

If your TV contains a simple plain text string, a number, or a boolean (Yes/No) value, there's no reason to get the rendered value, the raw value will be fine. In the case of dates, it will be faster to get the raw value and convert it to the desired format yourself.

If, on the other hand, the TV contains tags that must be processed or an @ binding that the parser needs to deal with, you want the rendered version rather than the raw value. We'll discuss how to get either value in a bit.

From the Resource

If you have a reference to the Resource or can use the current resource ($modx->resource in a snippet or $resource in a plugin), you can get the value of a TV with this code:

$tvId = 12;
$tvValue = $resource->getTVValue($tvId);

The method above tends to be the slowest, because it will always give you the rendered value of the TV. There's no way to get the raw value of a TV via the resource. That said, if you have a reference to the resource and don't have a reference to the TV, this method will probably be faster than getting the TV and then getting its value for the resource.

From the TV

If you have a reference to the TV, you can get either the rendered or the raw value by using the ID of the resource you want the value for as follows:

$resourceId = 12;
/* Get Raw Value */
$tvValue = $tv->getValue($resourceID);

/* Get rendered value */
$tvValue = $tv->renderOutput($resourceId);

The Fast Method

This method is significantly faster than either of the above methods, but it will only get you the raw value of the TV and it requires you to have the ID of both the TV and the Resource, so its use is limited. The up side is that you don't need either the TV object or the resource object to get the value.

TV values are stored in their own table. It's a very simple table where each row has three fields:

  • tmplvarid — The ID of the Template Variable
  • contentid — The ID of the Resource
  • value — The Value of the TV for that Resource

The object represented by that table is the modTemplateVarResource object. If you know the IDs of the resource and the TV, it's possible to go directly to that table to get the value.

$fields = array(
    'tmplvarid' => 12,  /* TV ID */
    'contentid' => 22,  /* Resource ID */
);

$tvr = $modx->getObject('modTemplateVarResource', $fields);
$tvValue = $tvr->get('value');

A Word of Warning

The code just above is not really safe due to a fact that trips up many MODX coders dealing with TVs. A TV set to the default value does not have a record in the table that stores TV values. That means that if the code above runs into such a TV, the getObject() call will fail and the get() call on the next line will throw a TV error since the $tvr variable will be null.

Here is the fix for that:

$fields = array(
    'tmplvarid' => 12,  /* TV ID */
    'contentid' => 22,  /* Resource ID */
);

$tvr = $modx->getObject('modTemplateVarResource', $fields);
if ($tvr) {
    $tvValue = $tvr->get('value');
} else {
    /* getObject() failed -- get the default value of the TV */
    $tv = $modx->getObject('modTemplateVar', 12);
    $tvValue = $tv->get('default_text');
}

Remember too, that this method can only be used when you want the raw value of the TV and you have the IDs of the TV and the resource.

Coming Up

In the next article, we'll see how to get TV values for the children of the current resource.



Comments (1)

  1. Dylan WoodMar 07, 2018 at 11:14 AM

    Hey... the solution on this page is missing! I'm seeing the exact error in my log... any advice... it looks like the above just got blanked out? Perhaps a getTVValue issue? hehehe


Please login to comment.

  (Login)