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.
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
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
This table shows the most common anomalies
|Object||'Name' field||Primary Key name|
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
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
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
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
$lexicon objects, which have no use for either a
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
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.