When you create a custom object class that will be stored in a database table in MODX, one of your first decisions is whether to have it extend xPDOObject or xPDOSimpleObject (or one of the accessible object classes, which we'll get to in a bit).
One of the confusing things about xPDOObject and xPDOSimpleObject is that, of the two, an xPDOObject is simpler.
An xPDOObject is a database object with no pre-set fields. Any fields it has are set in the object's schema and generated when the class and map files are created.
Any class that descends from xPDOObject will inherit all the basic xPDO methods like
An xPDOSimpleObject extends xPDOObject and is identical except that it adds a built-in, autoincrement field named
id. If you're creating an object for MODX and use xPDOSimpleObject as its base class, you don't have to put the
id field in your schema because it will inherit that automatically from the base class.
Since xPDOSimpleObject extends xPDOObject, classes that descend from it will have all the same methods as its parent.
If your object extends xPDOObject and includes in its schema an autoincrement
id field as its primary key, it is essentially equivalent to one that extends xPDOSimpleObject.
A common mistake when creating a custom database object class in MODX is to extend xPDOObject and then forget to include an 'id' field in the object's schema. In this case, many of the xPDO methods will not work on the object because they expect it to have an
It's my opinion that any MODX object that there will be more than one of should have xPDOSimpleObject as its base class (with the exception of objects that will be subject to the permission system — see below). That excludes singleton-style objects like the
$modx object itself and the
$lexicon object, but any database table that will contain multiple rows should have an
id field and the most reliable way to accomplish that is to extend xPDOSimpleObject. (Another exception to this would be objects with a compound key.)
There are exceptions to this in MODX. Contexts, for example, have no
id field and their primary key is
key. Namespaces and System Events have
name for their primary key.
If you need to get the primary key of a MODX object in code, you can find it like this:
$primaryKey = $modx->getPK('className');
getPK() method will return the primary key name, or in the case of compound keys, an array of primary key names. If no primary key is defined for the class, it will return
To get the type of the primary key (e.g., string, int), you can use this:
$primaryKeyType = $modx->getPKType('className', $pk);
The second argument is optional. If you know the name of the primary key, it will speed things up a tiny bit to include it, but in the case of objects with compound keys, the
$pk must be an array, so if you're not sure about the proper value for
$pk, just leave it out and MODX will find it for you.
If you look at the class files for
modElement, you'll see that they don't extend either xPDOObject or xPDOSimpleObject. That's because access to them is limited by the MODX security permission system. As a result, they extend modAccessibleSimpleObject. modAccessibleSimpleObject extends modAccessibleObject, which is the base class for all objects that you need some permission to access.
modAccessibleSimpleObject descends, ultimately from xPDOObject, which means that it doesn't automatically include an
id field from the base class, but the
id primary field is in its schema, so it has one.
If you create an object that you want to limit access to, it should extend either modAccessibleSimpleObject or modAccessibleObject. It will have a built-in, autoincrement
id primary key if it extends modAccessibleSimpleObject. If instead, it extends modAccessibleObject, it won't.
The bottom line is that if any class that is an ancestor of your object contains the word "Simple" in its class name, it will have a built-in, autoincrement primary key called
id. If it doesn't, it won't.