1. Overview
      1. What It Is
      2. Why I Would Want to Use It
      3. Known Issues
    2. Getting Started
      1. Fundamentals
        1. Design Patterns
        2. xPDO, the Class
          1. As Object and Relational Mapper
          2. As PDO Wrapper
          3. As Service Layer
          4. The xPDO Constructor
            1. Hydrating Fields
      2. Introduction to the xPDO Object Model
        1. Understanding xPDOCriteria and xPDOQuery
      3. Creating a Model With xPDO
        1. Defining a Schema
          1. Defining Relationships
          2. Defining the Database and Tables
            1. Upgrading Models to Schema Version 1.1
          3. More Examples of xPDO XML Schema Files
          4. Validation Rules in your Schema
        2. Generating the Model Code
          1. Domain Classes
          2. O-R Maps
          3. Table Classes
      4. Using Your xPDO Model
        1. Creating Objects
        2. Database Connections and xPDO
        3. Loading Packages
        4. Removing Objects
          1. removeCollection
        5. Retrieving Objects
          1. getCollectionGraph
        6. Setting Object Fields
        7. Working with Related Objects
    3. Extending Your xPDO Model
      1. Overriding Derived Behavior
        1. Using Custom Object Loaders
      2. Working With Transient Object Classes
    4. Advanced Features
      1. Caching
        1. Caching Tutorial - Basic Snippets
        2. Caching Tutorial - Lifetimes
      2. Object Validation
        1. xPDOForeignKeyConstraint
        2. xPDOMaxLengthValidationRule
        3. xPDOMaxValueValidationRule
        4. xPDOMinLengthValidationRule
        5. xPDOMinValueValidationRule
        6. xPDOObjectExistsValidationRule
    5. xPDO Development
      1. Testing
      2. Building
      3. Documentation and Tutorials
    6. Class Reference
      1. xPDO
        1. xPDO.addPackage
        2. xPDO.beginTransaction
        3. xPDO.commit
        4. xPDO.connect
        5. xPDO.fromJSON
        6. xPDO.getCollection
        7. xPDO.getCollectionGraph
        8. xPDO.getCount
        9. xPDO.getDebug
        10. xPDO.getFields
        11. xPDO.getIterator
        12. xPDO.getManager
        13. xPDO.getObject
        14. xPDO.getObjectGraph
        15. xPDO.getOption
        16. xPDO.getTableName
        17. xPDO.loadClass
        18. xPDO.log
        19. xPDO.newObject
        20. xPDO.newQuery
        21. xPDO.query
        22. xPDO.setDebug
        23. xPDO.setLogLevel
        24. xPDO.setLogTarget
        25. xPDO.setOption
        26. xPDO.toJSON
      2. xPDOCacheManager
        1. xPDOCacheManager.copyFile
        2. xPDOCacheManager.copyTree
        3. xPDOCacheManager.delete
        4. xPDOCacheManager.deleteTree
        5. xPDOCacheManager.endsWith
        6. xPDOCacheManager.escapeSingleQuotes
        7. xPDOCacheManager.get
        8. xPDOCacheManager.getCachePath
        9. xPDOCacheManager.getCacheProvider
        10. xPDOCacheManager.matches
        11. xPDOCacheManager.replace
        12. xPDOCacheManager.set
        13. xPDOCacheManager.writeFile
        14. xPDOCacheManager.writeTree
      3. xPDOGenerator
        1. xPDOGenerator.parseSchema
        2. xPDOGenerator.writeSchema
      4. xPDOManager
        1. xPDOManager.createObjectContainer
        2. xPDOManager.createSourceContainer
        3. xPDOManager.removeObjectContainer
        4. xPDOManager.removeSourceContainer
      5. xPDOObject
        1. Configuration Accessors
          1. getOption
          2. setOption
        2. Field Accessors
          1. fromArray
          2. fromJSON
          3. get
          4. set
          5. toArray
          6. toJSON
        3. Metadata Accessors
          1. getFieldName
          2. getFKClass
          3. getFKDefinition
          4. getPK
          5. getPKType
          6. getSelectColumns
        4. Persistence Methods
          1. remove
          2. save
        5. Related Object Accessors
          1. addMany
          2. addOne
          3. getMany
          4. getOne
        6. State Accessors
          1. isDirty
          2. isLazy
          3. isNew
        7. Static Object Loaders
          1. _loadCollectionInstance
          2. _loadInstance
          3. _loadRows
          4. load
          5. loadCollection
          6. loadCollectionGraph
          7. Using Custom Loader Classes
        8. Validation
          1. addValidationRule
          2. getValidator
          3. isValidated
          4. removeValidationRules
          5. validate
      6. xPDOQuery
        1. xPDOQuery.andCondition
        2. xPDOQuery.groupby
        3. xPDOQuery.innerJoin
        4. xPDOQuery.leftJoin
        5. xPDOQuery.limit
        6. xPDOQuery.orCondition
        7. xPDOQuery.rightJoin
        8. xPDOQuery.select
        9. xPDOQuery.setClassAlias
        10. xPDOQuery.sortby
        11. xPDOQuery.where
      7. xPDORevisionControl
      8. xPDOTransport
        1. xPDOTransport.install
        2. xPDOTransport.pack
        3. xPDOTransport.uninstall
      9. xPDOValidator
        1. xPDOValidator.addMessage
        2. xPDOValidator.getMessages
        3. xPDOValidator.hasMessages
        4. xPDOValidator.validate

Validation Rules in your Schema

Created by Everett Griffiths on Oct 25, 2013.

Overview

Your XML schema can define validation rules using nodes in the XML that follow this pattern

<validation>
    <rule field="$name_of_field" 
    name="$name_of_rule" 
    type="callback|preg_match|xPDOValidationRule" 
    rule="$various" 
    value="$optional_parameter"
    message="string" />
</validation>

The rule may have have these attributes:

  • field: the field's name. (required)
  • name: a unique name for this validation rule. You can have multiple validation rules for each field. (required)
  • type: can be "callback", "preg_match" or "xPDOValidationRule" (required)
  • rule: varies depending on the type. For type=callback, this will be the name of the callback function. For type=preg_match, this will be the regular expression. For type=xPDOValidationRule, a valid child class must be supplied. (required)
  • value: an optional argument to pass to the validation functions, e.g. when the type is xPDOValidationRule and the rule is a class that extends it. (optional)
  • message: this is a string describing the the validation rule if it fails. (required)

    In MODX 2+, the message field contains a lexicon string which can provide language specific message translations.

            <rule field="category" name="preventBlank" type="xPDOValidationRule" rule="xPDOMinLengthValidationRule" value="1" message="category_err_ns_name" />
    		

Regex Validation

Let's take this example from the modChunk schema:

    <object class="modChunk" table="site_htmlsnippets" extends="modElement">
        <field key="name" dbtype="varchar" precision="50" phptype="string" null="false" default="" index="unique" />
        <!-- ... more fields here -->
        <validation>
            <rule field="name" name="invalid" type="preg_match" rule="/^(?!\s)[a-zA-Z0-9\x2d-\x2f\x7f-\xff_-\s]+(?!\s)$/" message="chunk_err_invalid_name" />
        </validation>
    </object>

Callback Validation

You can use your own functions for validation purposes by using "callback" as the type -- this relies on PHP's call_user_func() function. Because the function name is defined in XML where it is impossible to reference an object instance, you can only reference a regular PHP function like my_function or a static class method, e.g. MyClass::myFunction. Likewise, you cannot pass parameters to these functions (?).

xPDOValidationRule Validation

This is how you can tie-into the built-in MODX validation rules. See the classes available inside the core/xpdo/validation/xpdovalidator.class.php file:

  • xPDOMinLengthValidationRule
  • xPDOMaxLengthValidationRule
  • xPDOMinValueValidationRule
  • xPDOMaxValueValidationRule
  • xPDOObjectExistsValidationRule
  • xPDOForeignKeyConstraint

For example, look a the the rule defined for the modContentType

    <object class="modContentType" table="content_type" extends="xPDOSimpleObject">
        <field key="name" dbtype="varchar" precision="255" phptype="string" null="false" index="unique" />
        <!-- ... more fields here ... -->
        <validation>
            <rule field="name" name="name" type="xPDOValidationRule" rule="xPDOMinLengthValidationRule" value="1" message="content_type_err_ns_name" />
        </validation>
    </object>

Using xPDOValidator

You can use the xPDOValidator to pre-validate the current state of an xPDOObject or you can allow save() to call validation (see xPDO::OPT_VALIDATE_ON_SAVE) itself and fail if validation fails.

An example of pre-validation from MODX Revolution's modObjectCreateProcessor class:

/* run object validation */
if (!$this->object->validate()) {
    /** @var modValidator $validator */
    $validator = $this->object->getValidator();
    if ($validator->hasMessages()) {
        foreach ($validator->getMessages() as $message) {
            $this->addFieldError($message['field'],$this->modx->lexicon($message['message']));
        }
    }
}

An example of examining the validation messages after save() failure from MODX Revolution's modError class:

/* save object and report validation errors */
if (!$this->object->save()) {
    /** @var modValidator $validator */
    $validator = $this->object->getValidator();
    if ($validator->hasMessages()) {
        foreach ($validator->getMessages() as $message) {
            $this->addFieldError($message['field'],$this->modx->lexicon($message['message']));
        }
    }
}

Writing Your Own Validation Rules

If you want to write your own validation rules, you need to create a PHP class file inside of your namespace's model folder for each validation rule you define, e.g. core/components/my_pkg/model/my_pkg/my_validation_rule.class.php. The name should be all lowercase and include a .class.php extension. This is how xPDO knows how to find your class file (this is xPDO's "autoload-like" convention).

Let's look at a Custom Resource Class (CRC) that does not want to be nested under other CRC's -- it wants as its parent only the built-in MODX classes (modDocument, a WebLink, etc). Here's its XML schema definition:

    
        
        
            
        
    

And here's the corresponding validation rule from core/components/my_pkg/model/my_pkg/normalparents.class.php:

validator->object;
        $xpdo=& $obj->xpdo;
                $xpdo->log(1, 'Running TaxonomyParents Validation rule');
        $validParentClasses = array('modDocument', 'modWebLink', 'modSymLink', 'modStaticResource');
        if ($obj->get('parent') === 0 || ($obj->Parent && in_array($obj->Parent->class_key, $validParentClasses))) {
           $result = true; 
        }
        if ($result === false) {
            $this->validator->addMessage($this->field, $this->name, $this->message);
        }
 
        return $result;
    }
}

Suggest an edit to this page on GitHub (Requires GitHub account. Opens a new window/tab) or become an editor of the MODX Documentation.