Understanding MODX Revolution Objects and xPDO

I collected this information about MODX objects for my own reference, but thought I'd make it public in case anyone else might find it useful.

The information on this page is only useful for MODX developers writing PHP code in snippets or plugins, who need to understand how to interact with resources (documents, weblinks, symlinks, and static resources) and elements (chunks, snippets, plugins, templates, template variables, and categories) in MODX Revolution.

This page is also a quick introduction to xPDO. It introduces the basic xPDO methods used to deal with the various objects in MODX Revolution. Many of the methods listed here are xPDO methods, but since the $modx object is a descendant of the $xpdo object, all are available with $modx->methodName().

For a quick reference to all MODX objects, go here.

For a more technical, full reference to all MODX Objects, go here.

Current Resource / Current User

The current resource and user are available directly in the following MODX class member variables:

$currentResource = $modx->resource;
$currentUser = $modx->user;
/* If the user is not logged in, the username will be '(anonymous)'. */

The fields of the objects are available through each object's get() method (or getContent() for the resource's content field):

$intro = $modx->resource->get('introtext');
$UserID = $modx->user->get('id');
$content = $modx->resource->getContent();

Note that for resources, using either get('content') or getContent(), will retrieve the raw content of the resource's content field. Tags in the content field will not have been processed.

Finding Other Objects

In revolution, references to all MODX objects can be retrieved using the $modx->getObject() method.

You can "get" a MODX object like this:

$object = $modx->getObject('object-class-name',array(
       'name' => 'object-name' ));

Or, to get the object by ID number:

$object = $modx->getObject('object-class-name',$object-id); 

To get a reference to a chunk, for example, you would use:

$chunk = $modx->getObject('modChunk',array(
       'name' => 'chunkName' ));

This will also work to retrieve a chunk, and is somewhat faster if you know the ID of the chunk. It's also more reliable since the name of the chunk might change, but the ID never will:

$chunk = $modx->getObject('modChunk',$chunkId);

Using the ID will work with any type of object.

To get a resource (formerly called a "document") that is published and has the name "Recipes," you'd do this:

$document = $modx->getObject('modResource',array(
    'published' => 1,
    'pagetitle' => 'Recipes'
));

Here's another way of doing the same thing:

$name = 'modResource';
$criteria = array(
    'published' => 1,
    'pagetitle' => 'Recipes'
)
$document = $modx->getObject($name,$criteria)

Note: A common mistake when getting a resource is to use 'name' or 'title' instead of 'pagetitle'. Resources do not have a 'name' or 'title' field even though the caption on the Create/Edit Resource panel for the pagetitle field is 'title.'

You can also find a resource by specifying its id, alias, menu title, and/or any of the fields listed in the table below. If you want an array of documents meeting your criteria, you can use getCollection() instead of getObject():

$docArray = $modx->getCollection('modResource',array(
    'published' => 1,
    'searchable' => 1
));

Remember that getCollection() does not return a PHP array. It returns an array of objects. If you would like the objects fields as a PHP array, you can use the object's toArray() method:

$phpArray = $object->toArray();

You can also use the object's get() method to get any individual field:

$resource->get('pagetitle');

As we saw with getObject(), you can also use a query as your criterion for either getCollection() or getMany():

$tvCollection = $modx->getCollection('modTemplateVar', 
    "`name` IN ('" . implode("','", array('footer', 'header')) . "')");

Note that you must use the fields shown in the table below with getObject(). For example, you'd use 'pagetitle' to find a document, but 'name' to find a snippet or chunk.

If you want only the related objects associated with a single object, you can use the object's getMany() method. Assuming that you have used getObject() to get a reference to a resource or template, you can get their associated TVs like this:

$tvs = $template->resource->getMany('TemplateVars');

Similarly, you can get the children like this:

$children = $resource->getMany('Children');

getObject() and getOne() return null if the requested object is not found, while getMany() and getCollection() return an empty array if there are no matches for the criteria given.

All individual resources (document, weblinks, symlinks and static resources) can retrieved with:

$modx->getObject('modResource',$criteria);

but you can also search for them individually:

$modx->getObject('modDocument',$criteria);
$modx->getObject('modWeblink',$criteria);
$modx->getObject('modSymlink',$criteria);
$modx->getObject('modStaticResource',$criteria);

Individual elements (chunks, snippets, plugins, templates, template variables, and categories) must be retrieved using the class key of the object desired:

$modx->getObject('modChunk',$criteria);
$modx->getObject('modSnippet',$criteria);
$modx->getObject('modPlugin',$criteria);
$modx->getObject('modTemplate',$criteria);
$modx->getObject('modTemplateVar',$criteria);
$modx->getObject('modCategory',$criteria);

Getting System Settings

System settings can be retrieved in a snippet with the getOption() method:

$setting = $modx->getOption('site_start');

Getting Object Fields with $object->get()

Once you have retrieved an object using getObject(), getCollection(), or getMany(), you can use the $object->get() method to retrieve any field by name:

$resource = $modx->getObject('modResource',12);
$longTitle = $resource->get('longtitle');

The current document is always available as:

$modx->resource

You can get any of its fields using its get() method:

$id = $modx->resource->get('id');
$name = $modx->resource->get('pagetitle');

As in MODX Evolution, any snippet tag is replaced by the return value of the snippet. So, if you want to display a field from an object you've retrieved. Just put something like this at the end of your snippet:

return $resource->get('pagetitle');

When using get('content') on a resource, you will get the raw value of the resource's content field. No tags in the content will have been processed.

Using $object->getOne() and $object->getMany() with objects

If an object has objects that are related to it in the MODX schema, they can be retrieved with the object's getOne() or getMany() methods. Resources, for example, have a related Parent, Children, Template, CreatedBy, EditedBy, etc. (see Tables below). While the get() function will retrieve the contents of a particular resource field of the object, the getOne() function will retrieve a whole object. The getMany() method will retrieve an array of objects. The key to knowing which one you need is whether there could possibly be more than one of what you're looking for. If so, you want getMany(). A resource, for example, has only one parent so you'd get it with getOne('Parent'). The same resource could have multiple template variables attached to it, however, so to retrieve them you need to use getMany('TemplateVars').

Note that while the field names used with get() are in all lower case, the object names used in the call to getOne() and getMany() are all in CamelCase. The getOne() and getMany() methods often take a single argument (the name of the related object(s) you want to get), but they can also take an optional second argument specifying criteria for the search. The second argument is also useful if you want to sort the results of getMany().

To retrieve the Resource ID of a resource's parent:

$id = $resource->get('parent');

To retrieve the parent resource itself as a MODX object:

$parentResource = $resource->getOne('Parent');

Similarly, to get the user object of the user who created a resource:

$user = $resource->getOne('CreatedBy');

Or, for the current resource:

$user = $modx->resource->getOne('CreatedBy');

The user object contains only the ID, username, and password hash of the user. To get more, you need to retrieve the modUserProfile object associated with that user:

$user->getOne('Profile');

Once you have the profile, you can use its get() method to retrieve any resource field:

$profile->get('fullname');

To get the children of a document, sorted by Title:

$criteria = $modx->newQuery('modResource');
$criteria->where(array(
   'parent' => $modx->resource->get('id'),
));
$criteria->sortby('pagetitle','ASC');
$children = $modx->resource->getMany('Children',$criteria);

Template Variables

Getting the processed value of a TV from the current document (or any document you have a reference to) is easy with this method (note that both instances of the letter 'V' in getTVValue() are capitalized):

$val = $modx->resource->getTVValue('name_of_tv');
$val = $modx->resource->getTVValue($id); // ID of the TV (not the document)

or

$resource = $modx->getObject('modResource',array('pagetitle'=>'SomePage'));
$val = $resource->getTVValue('name_of_tv');
$val = $resource->getTVValue($id); // ID of the TV (not the document)

Getting the value of a TV in another document is a little more tricky because the processed value of the TV can be different for each document it's embedded in. As a result, you have to either get the resource object using the method above, or use specific methods of the TV and send along the ID of the document. Assuming that $id is the ID of the document (not the TV):

/* Get the TV */
$tv = $modx->getObject('modTemplateVar',array('name'=>'MyTV'));

/* get the raw content of the TV */
$rawValue = $tv->getValue($id);

/* get the processed content of the TV */
$processedValue = $tv->renderOutput($id);

Using toArray() with getChunk()

MODX makes it easy to separate the display from the data. One really convenient way to do this, is to put placeholders in a chunk and then send the object fields along in a call to getChunk(). Say, for example, that you want to display some of the fields of a resource using a custom snippet. If you create a Tpl chunk with placeholders for the fields you want to show, you can display it in MODX Revolution with very few lines of code.

The toArray() method works with any MODX object, but is most often used with resources and users. It creates a PHP associative array from the fields of the object. That array can then be used as a second argument to $modx->getChunk() to replace any placeholders in the chunk with the appropriate values. This example shows how to display resource fields very efficiently. Imagine that you want to show the fields from a resource called MyDocument and that this is your ShowResource Tpl chunk:

<div class="ShowResource">
    <p>Page Title: [[+pagetitle]]</p>
    <p>Long Title: [[+longtitle]]</p>
    <p>Alias: [[+alias]]</p>
    <p>Summary: [[+introtext]]</p>
</div>

If you put the following snippet tag on a page, it will display the resource fields with the snippet below.

   [[!ShowFields]]

Here's the snippet code:

$resource = $modx->getObject('modResource',array('pagetitle'=>'MyDocument'));
$fields = $resource->toArray();
return $modx->getChunk('ShowResource',$fields);

Modx will replace all the placeholders in the Tpl chunk with the values of the $fields array which contains every field of the resource. A slightly faster, but less readable version of the snippet has only two lines:

$resource = $modx->getObject('modResource',array('pagetitle'=>'MyDocument'));
return $modx->getChunk('ShowResource',$resource->toArray());

If you want to display the fields of the current resource, the snippet gets even more compact:

return $modx->getChunk('ShowResource',$modx->resource->toArray());

Property Sets

A Property Set is a MODX object that contains an associative array of keys and values (much like System Settings). Property sets can be attached to elements either on the Properties tab of the element (available when editing the element in the Manager), or from Tools | Property Sets in the Main Menu of the Manager. An element can have more than one Property Set attached and a Property Set can be attached to more than one element. Attaching a property set makes it available for that element, but to actually use a property set with a snippet or chunk, it needs to be specified in the element's tag like this:

[[SnippetName@PropertySetName]]
[[$ChunkName@PropertySetName]]

When attached to a snippet, a Property Set plays the role of a set of snippet properties (formerly parameters). For a chunk or other element, the values in the Property Set will replace placeholder tags in the chunk that use keys from the Property Set. For example, with a property set called "MyProperties" that is attached to a chunk called "MyChunk," you'd have this in the chunk tag:

[[$MyChunk@MyProperties]]

If there is a property called "make" with a value of "Ford," the placeholder [[+make]] will be replaced by Ford in the displayed chunk.

When you call a snippet with a property set in the tag:

[[SnippetName@PropertySetName? &property1=`value1` &property2=`value2`]]

The values in the named Property Set will override the values in the Default Properties of the snippet and the properties sent in the snippet tag (&property1 and &property2) will override the values in the named property set. Of course this is only true for properties with the same name.

The same goes for other elements with attached Property Sets. The values in the Property Set will override any Default Properties with the same name.

Getting the Processed Output of an Object

In some cases, you might have the need in a snippet to get the processed output of a chunk or another snippet. The two functions, runSnippet() and getChunk(), are still available in Revolution. In this example for snippets, $props is an array containing the snippet's properties:

$modx->runsnippet($snippetName, $props);
$modx->getChunk($chunkName);

When you execute a snippet with runSnippet('SnippetName') in code, the default properties will be used. If you send a Property Set using runSnippet('SnippetName',$properties), both the Default Properties and those sent in the snippet tag will be available in the snippet. The ones sent in the snippet tag will override any Default Properties with the same name.

Placeholder tags in a chunk will be replaced with values from an attached Property Set, but how will those placeholders get processed when using getChunk() in a snippet? The answer is a second argument to getChunk() containing the properties array. Because multiple property sets can have the same name, you need to search for the right one by name:

$setName = 'desiredPropertySetName';
$chunkName = 'desiredChunkName';

$object = $modx->getObject('modChunk',array(
        'name' =>$chunkName));

$propSet = $modx->getObject('modPropertySet',array(
        'name' =>$setName));

return($modx->GetChunk($chunkName, $propSet->getProperties() ));

You should be aware of the difference between Property Sets, and the Default Properties available on the Properties tab of elements. Those Default Properties are not technically a Property Set. In fact, they are the equivalent of a Property Set's properties. The getProperties() method will get the properties of either one:

/* get the Default Properties of a snippet (or other element) */
$snippet = $modx->getObject('modSnippet',array('name'=>'SnippetName'));
$properties = $snippet->getProperties();

/* Get the properties of a particular Property Set */
$propSet = $modx->getObject('modPropertySet',array('name'=>'PropertySetName'));
$properties = $propSet->getProperties();

When a chunk is retrieved with getChunk(), the Default Properties will be available for placeholder tags in the chunk and will be overridden by any same-name properties sent in a getChunk('ChunkName',$properties) call.

A similar process is necessary if you want to send a property set along in a call to runSnippet(). The properties in the property set array will be available in the snippet as if they were entered as properties in the snippet tag. Again, the values sent in the snippet tag will override any same-name Default properties.

For other elements, once you get the element with $modx->getObject(), you can retrieve the processed output with a call to $element->process(). This works for chunks and snippets also (in fact, both the getChunk() and runSnippet() methods call the element's process() method). As you would guess, $element->process($properties) is also available and same-named properties sent in the element tag will override the Default Properties of the element.

You never need to send the Default Properties in call to getChunk(), runSnippet(), or process() call. They are used automatically.

Because elements can have more than one property set attached to them, it's always necessary to specify which property set you want, unless you want MODX to use the Default Properties.

This method works for resources as well. Once you've retrieved a resource object with $modx->getObject(), the processed content field of the resource is available with $resource->process(). Be careful not to call this for the current resource in a snippet contained in that resource to avoid an infinite loop.

Getting the Raw Content of an Object

In MODX, the raw content is just called the "content." For a chunk, the content is the HTML code of the chunk, including any placeholder tags. For a snippet, or plugin, it's the actual code. You would rarely, if ever, want to do this unless you're creating a utility snippet or plugin intended to modify the MODX DB or assist in debugging, but to get the content, you can use the following:

$object->getContent();

Of course you can get the content of individual fields with:

$object->get('fieldName')

See the table below for the appropriate field names, but remember that the field names might change in future versions (especially for chunks and snippets), which is why getContent() will be a better choice for the main content of the object, since it will automatically supply the correct field name.

Please note that dealing with object fields directly (and especially changing them) is not something that typical MODX developers do. It's not necessary for creating a web site, or even in a typical chunk, snippet, or plugin. It should only be done by those who really know what they are doing and then only when the built-in functions to get and set object contents won't do. An example might be a custom search and replace process for snippet or chunks, or a version control system for MODX. Even in those cases, using XPDO to alter the database itself might be a better solution.

The following information is here just to give you a better idea of how MODX handles objects and to provide a list of commonly used field names in each object. Note that the list is not complete and the individual field names may change in future releases (another reason to use the standard access functions).

Modifying Objects

After retrieving a reference to an object with $modx->getObject(), you can change the value of its fields like this:

$object->set('FieldName', 'Value');
$object->save();

To change or create the main Content field of a resource or element (e.g the "Content" field of resources, the content of chunks, the code of a snippet), always use setContent():

$object->setContent('Value');
$object->save();

You may know that a reference to the currently loaded resource is available with $modx->resource, but you should never use that to modify a resource because it is actually a copy of the resource. Always get a reference with $modx->getObject() before attempting to modify an object.

Creating New objects

Again, not something you are ever likely to do unless you are an add-on developer creating a build script. It should be done with care and with an understanding of which fields are necessarily filled for each object type. You can create new objects with:

$object = $modx->newObject('modChunk');
$object->set('name', 'ChunkName');
$object->setContent('This will be the content of the new chunk.');
$object->set('description', 'I created this chunk in a snippet');
$object->set('category', 'MyChunks');
$object->save(); 

Every object described here has an ID and can be found by it, but you should never, ever, set() the ID yourself. Also, when modifying or creating objects, be sure that the variable you use for the new value is of the correct type (i.e. the same as the type of the field you're setting). See the file /core/model/schema/modx.mysql.schema.xml for details about dbtypes, precision, etc.

Here is a list of the most commonly used objects with their class names and the names of some of their fields and field types. The related objects available with getOne() and getMany() are listed below the fields for each object:

Common Objects and Some of Their Properties

Document/Resource (class name = 'modResource')

  • id (int - Resource Identifier)
  • pagetitle (text)
  • isfolder (int 0/1)
  • longtitle (text)
  • description (text)
  • alias (text)
  • published (int 0/1)
  • introtext (text - aka summary)
  • content (text)
  • template (int - template id number)
  • menuindex (int)
  • searchable (int 0/1)
  • cacheable (int 0/1)
  • createdby (int user id number)
  • editedby (int user id number)
  • deleted (int 0/1)
  • deletedby (int user id number)
  • publishedby (int user id number)
  • createdon (date - date of first save)
  • publishedon (date - date of most recent change to published)
  • editedon (date - date it was last edited)
  • menutitle (text)
  • donthit (int 0/1) (deprecated)
  • haskeywords (int 0/1) (deprecated)
  • hasmetatags (int 0/1) (deprecated)
  • hidemenu (int 0/1)
  • Related Objects available with getOne()
    • Parent (class="modResource")
    • Template (class="modTemplate")
    • CreatedBy (class="modUser")
    • EditedBy (class="modUser")
    • DeletedBy (class="modUser")
    • PublishedBy (class="modUser")
    • ContentType (class="modContentType")
    • Context (class="modContext")
  • Related Objects available with getMany()
    • Children (class="modResource")
    • TemplateVars (class="modTemplateVar")
    • TemplateVarTemplates (class="modTemplateVarTemplate")

Chunk (class name = 'modChunk')

  • name (text)
  • description (text)
  • category (int - category id number)
  • snippet (text - chunk's contents)
  • locked (int 0/1 - AKA locked for editing)
  • Related Objects available with getOne()
    • Category (class="modCategory")
  • Related Objects available with getMany()
    • PropertySets (class="modElementPropertySet")

Snippet (class name = 'modSnippet')

  • name (text)
  • description (text)
  • category (int - category id number)
  • snippet (text - snippet's contents)
  • locked (int 0/1 - AKA locked for editing)
  • properties (text)
  • Related Objects available with getOne()
    • Category (class="modCategory")
  • Related Objects available with getMany()
    • PropertySets (class="modElementPropertySet")

Plugin (class name = 'modPlugin')

  • name (text)
  • description (text)
  • category (int - category id number)
  • plugincode (text - plugin's contents)
  • locked (int 0/1 - AKA locked for editing)
  • properties (text)
  • disabled (int 0/1)
  • Related Objects available with getOne()
    • Category (class="modCategory")
  • Related Objects available with getMany()
    • PropertySets (class="modElementPropertySet")
    • PluginEvents (class="modPluginEvent")

Template (class name = 'modTemplate')

  • templatename (text)
  • description (text)
  • category (int - category id number)
  • content (text)
  • icon (text)
  • locked (int 0/1)
  • Related Objects available with getOne()
    • Category (class="modCategory")
  • Related Objects available with getMany()
    • PropertySets (class="modElementPropertySet")
    • TemplateVarTemplates (class="modTemplateVarTemplate")

TemplateVariable (class name = 'modTemplateVar')

  • type (text)
  • name (text)
  • caption (text)
  • description (text)
  • category (int - category id)
  • locked (int 0/1)
  • elements (text)
  • rank (int)
  • display (text)
  • display_params (text)
  • default_text (text)
  • Related Objects available with getOne()
    • Category (class="modCategory")
  • Related Objects available with getMany()
    • PropertySets (class="modElementPropertySet")
    • TemplateVarTemplates (class="modTemplateVarTemplate")
    • TemplateVarResources (class="modTemplateVarResource")
    • TemplateVarResourceGroups (class="modTemplateVarResourceGroup")

User (class name = 'modUser')

  • username (text)
  • password (text)
  • cachepwd (text)
  • Related Objects available with getOne()
    • Profile" (class="modUserProfile")
  • Related Objects available with getMany()
    • CreatedResources (class="modResource")
    • EditedResources (class="modResource")
    • DeletedResources (class="modResource")
    • PublishedResources (class="modResource")
    • SentMessages (class="modUserMessage")
    • ReceivedMessages (class="modUserMessage")
    • UserSettings (class="modUserSetting")
    • UserGroupMembers (class="modUserGroupMember")

User Profile (class name = 'modUserProfile')

  • fullname (text)
  • role (int)
  • email (text)
  • phone (text)
  • mobilephone (text)
  • blocked (int 0/1)
  • blockeduntil (int - date)
  • blockedafter (int - date)
  • logincount (int)
  • lastlogin (int - date)
  • thislogin (int - date)
  • failedlogincount (int)
  • sessionid (text)
  • dob (int - date)
  • gender (int 0/1)
  • country (text)
  • state (text)
  • zip (text)
  • fax (text)
  • photo (text)
  • comment (text)
  • Related Objects available with getOne()
    • User (class="modUser")
    • UserRole (class="modUserRole")

Deprecated Methods

In MODX Revolution, many of the methods once used for getting document information are gone or deprecated (to be removed soon).

The following methods are deprecated in MODX Revolution (and most have been removed as of MODX 2.1):

  • getSettings()
  • getDocumentObject()
  • getLoginUserType()
  • getDocument()
  • getDocuments()
  • getUserDocGroups()
  • getFullTableName()
  • getAllChildren()
  • getActiveChildren()
  • getDocumentChildren()
  • getDocumentChildrenTVars()
  • getTemplateVar()
  • getTemplateVars()
  • getTemplateVarOutput()
  • getParent()
  • getPageInfo()
  • getUserInfo()
  • getWebUserInfo()
  • getDocGroups()
  • changeWebUserPassword()
  • changePassword()
  • cleanDocumentIdentifier()
  • getDocumentIdentifier()
  • getDocumentMethod()
  • checkPreview()
  • logEvent()
  • getManagerPath()
  • userLoggedIn()
  • mergeDocumentContent()
  • mergeSettingsContent()
  • mergeChunkContent()
  • mergePlaceholderContent()
  • isBackend()
  • isFrontend()
  • insideManager()
  • putChunk()

 

My book, MODX: The Official Guide - Digital Edition is now available here. The paper version of the book is available from Amazon.

If you have the book and would like to download the code, you can find it here.

If you have the book and would like to see the updates and corrections page, you can find it here.

MODX: The Official Guide is 772 pages long and goes far beyond this web site in explaining beginning and advanced MODX techniques. It includes detailed information on:

  • Installing MODX
  • How MODX Works
  • Working with MODX resources and Elements
  • Using Git with MODX
  • Using common MODX add-on components like SPForm, Login, getResources, and FormIt
  • MODX security Permissions
  • Customizing the MODX Manager
  • Using Form Customization
  • Creating Transport Packages
  • MODX and xPDO object methods
  • MODX System Events
  • Using PHP with MODX

Go here for more information about the book.

Thank you for visiting BobsGuides.com

  —  Bob Ray