MODX Object Names and Keys: A Source of Confusion

Many new MODX programmers stumble over the anomalies in the Names and Primary Keys of MODX Objects


The names and primary keys of MODX objects can be frustrating to new users trying to write MODX PHP code to work with them. Most MODX objects have a primary key called id, but some don't. You can also get the name of a MODX object by getting its name field, but not always.

This post lists some of the anomalies, and contains a plea to regularize things a bit for MODX 3.

The Problem

Almost every new MODX programmer tries to get a modResource object with code something like this:

$doc = $modx->getObject('modResource', 
    array('name' => 'MyResource'));

It doesn't work because a modResource Object has no name field. The correct field to use is pagetitle.

Similarly, it's tempting to try to get a Context object with code like this:

$ctx = $modx->getObject('modContext', 
    array('id' => 'web'));

That doesn't work either because the primary key of a context is called key.

The Anomalies

This table shows the most common anomalies

Object 'Name' field Primary Key name
modResource pagetitle id
modTemplate templatename id
modCategory category id
modContext key key
modNamespace name name
modAction (none) id
modEvent name name
modMenu text text
modSession (none) id

Intersect Objects

Lots of MODX objects have an "intersect" object that ties them to their related objects. Intersect objects never have a name or ID. They can be recognized by the fact that their names combine the names of two separate objects (modPluginEvent, modTemplateVarResource, modContextSetting, modUserSetting, modUserProfile, etc.).

For example, a Resource can have many Template Variables and a Template Variable can have values for many Resources. To connect them, we have the modTemplateVarResource object. That object has no name field and no id field. Instead it has a tmplvarid field, which contains the ID of the Template Variable it refers to, and a contentid field that contains the ID of the Resource it refers to. The value field contains the value of the tmplvarid Template Variable for the contentid Resource.

These intersect objects always have a compound primary key. In other words, instead of an ID, they have two fields, each of which points to one of the two objects connected by the intersect object. Sometimes, as in the modTemplateVarResource example above, the two fields contain IDs. As we saw earlier, however, not every object has an ID.

For the modPluginEvent intersect object, for example, the pluginid field contains the ID of the plugin, but the event field contains a string, which is the name of the event. The primary key of an event object is a string containing the name of the event rather than an ID (e.g., OnDocFormSave, OnWebPagePrerender, etc.)

A Plea for Normalization

The anomalies listed in the table above can lead to some fairly inelegant code when you're trying to process multiple MODX objects. The MyComponent extra is a prime example. It's littered with code that handles these anomalies. Code that creates a named object like a category, namespace, menu, context, resource, or element, has to be aware that these objects don't always have a name or id field.

Clever coding can help deal with the problem, but with the side effect that the code is more difficult to understand and maintain. Life would be a lot simpler if these objects all had a name field and a primary key of id.

Obviously, this can't be done for the intersect objects, which require compound keys and don't need a name. It also doesn't make sense for the singleton-type objects like the $modx, $xPDO, and $lexicon objects, which have no use for either a name or id field.

It would be great, though, if the other objects all had a name field called "name" and a primary key field called "id."

To keep from breaking legacy code, requests for the old name or primary key fields could return the new value. For example, $template‑>get('templatename') could return the value of the new name field.

Messing with the primary keys might be too complex to implement without breaking existing code, but it should be possible to have all these objects respond sensibly to $object‑>get('name'). I'm hoping that MODX 3 will at least take some steps in this direction.



Comments (0)


Please login to comment.

  (Login)