Tony Marston's Blog About software development, PHP and OOP

RADICORE for PHP - Extending the Validation class

Posted on 9th September 2006 by Tony Marston

Amended on 15th January 2007

Introduction
Create a class with custom validation methods
Identify where a custom method is to be used
Amendment History
Comments

Introduction

The RADICORE framework contains a standard module for performing primary validation which ensures that required fields are not empty, date fields contain dates, numeric fields contain numbers, etc. This standard module is called automatically by the framework before any user input is made available to a custom method in any database table class, after which any secondary validation can be performed with custom code inside that table class.

However, there may be certain validation rules that are, or may be, required in several places, or even shared between different projects, and rather than have that code duplicated in all those different places it would be a good idea to have a method of creating a plug-in for this validation code and have the framework use that plug-in for designated fields without the need for additional custom code within each database table class. This article will show you how this can be done, using sample code that is included in the framework download.

This is basically a two step process:

The framework is able to support any number of custom classes, and each class can have any number of methods. A field may only be processed by a single custom method.

Create a class with custom validation methods

Here is a copy of the sample which is supplied in the framework download:

filename = sample.validation.class.inc  <-- (1)

<?php
// *****************************************************************************
// Copyright 2003-2005 by A J Marston <http://www.tonymarston.net>
// Copyright 2006 by Radicore Software Limited <http://www.radicore.org>
// *****************************************************************************
class sample_validation_class  <-- (2)
{
    // ****************************************************************************
    // This is an example of a custom validation class for the RADICORE framework.
    // ****************************************************************************
    // This uses the following error manages:
    //
    // $array['sample001'] = "Invalid format for a postcode.";          <-- (3)
    // $array['sample002'] = "Invalid format for a telephone number.";  <-- (3)
    // $array['sample003'] = "Invalid format for a fax number.";        <-- (3)
    //
    // These messages should be added to your 'language_text.inc' file
    //
    // ****************************************************************************
    function sample_validation_class()  <-- (4)
    {
        // custom code goes here

    } // sample_validation_class

    // ****************************************************************************
    function postcode (&$input, $fieldspec)  <-- (5)
    // perform validation that is common to INSERT and UPDATE.
    {
        $input = strtoupper($input);
        
        if (!empty($input)) {
            $pattern = "^[A-Z]{1,2}[0-9]{1,2}[A-Z]{0,1} [0-9]{1}[A-Z]{2}$";
            if (!ereg($pattern, $input)) {
                // 'Invalid format for a postcode.'
                return getLanguageText('sample001');  <-- (6)
            } // if
        } // if

        return;  <-- (7)

    } // postcode

    // ****************************************************************************
    function telephone_no (&$input, $fieldspec)  <-- (5)
    // perform validation that is common to INSERT and UPDATE.
    {
        if (!empty($input)) {
            $pattern = "^([0-9]{3,5})[ ][0-9]{3,4}[ ]([0-9]{3,4})$";
            if (!ereg($pattern, $input)) {
                // 'Invalid format for a telephone number.'
                return getLanguageText('sample002');  <-- (6)
            } // if
        } // if

        return;  <-- (7)

    } // telephone_no

    // ****************************************************************************
    function fax_no (&$input, $fieldspec)  <-- (5)
    // perform validation that is common to INSERT and UPDATE.
    {
        if (!empty($input)) {
            $pattern = "^([0-9]{3,5})[ ][0-9]{3,4}[ ]([0-9]{3,4})$";
            if (!ereg($pattern, $input)) {
                // 'Invalid format for a fax number.'
                return getLanguageText('sample003');  <-- (6)
            } // if
        } // if

        return;  <-- (7)

    } // fax_no

// ****************************************************************************
} // end class
// ****************************************************************************

?>

Please note the following numbered items:

  1. The file name must not conflict with any other file used by the framework (Doh!) If it is placed in your subsystem's classes directory it will only be available to that one subsystem. If the contents are to be accessible to multiple subsystems then it can be placed in the global includes directory.
  2. The class name must not conflict with any other class used by the framework (Doh!)
  3. Error messages must be given unique identifiers so that they can be copied to the relevant language_text.inc file, as identified in Internationalisation and the Radicore Development Infrastructure. This will allow the message text to be available in multiple languages.
  4. This is the class constructor. In this example it is empty, but it your code it may not be.
  5. This is the method name, which must be unique within the class (Doh!) but need not be unique within the framework. It can be anything you like, but something meaningful would be nice. Notice that the $input value is passed by reference so that it can be changed before it is returned. The contents of the $fieldspec array is also made available in case it is needed.
  6. This is how to return a validation failure, with the relevant error message. Note that it uses the getLanguageText() method so that the message may be output in different languages.
  7. This is how to return a validation success.

When a custom validation method is specified the only checking performed by the framework will be:

Everything else is the responsibilty of the custom method.

Identify where a custom method is to be used

This is a very simple process - go to the Data Dictionary and use the Update Column task on the relevant field (column) to identify the custom validation method which is to be used, as shown in the following screen shot:

custom-valdation-001 (1K)

Note that the custom validation method has three distinct parts which are presented in the format '<file>/<class>/<method>'.

You must then run the dictionary export process in order to update the <tablename>.dict.inc file which is used by the application at runtime.

That's all there is to it. Don't applaud, just throw money.


Amendment history:

15 Jan 2007 Added the $fieldspec argument to each custom method in case it is needed.
Made this feature available on any field, and without the need to set SUBTYPE=CUSTOM.
18 Nov 2006 Changed the $input value so that it is passed by reference. This will allow the value to be changed (e.g. shifted to upper case) before it is returned.

counter