Jump to content

Custom Validation Logic: Difference between revisions

From NusaATK
anti spam
 
(6 intermediate revisions by 2 users not shown)
Line 13: Line 13:
Code:
Code:


  function test_validate(&$record, $mode)
<syntaxhighlight lang="php">
  {
public function test_validate(&$record, $mode)
     if ($record["test"]!="something")
{
    {
     if ($record["test"]!="something") {
      triggerError($record, "test", "Test field should be 'something'");
        atkTriggerError($record, $this->getAttribute("test"), "Test field should be 'something'");
     }
     }
  }
}
</syntaxhighlight>


This is the prefered way of adding custom validation to a node.
This is the prefered way of adding custom validation to a node.


The $mode param is either 'add' or 'update', so you could do validation based on the fact if the user was adding a new record or updating an existing one.
The $mode param is either 'add' or 'update', so you could do validation based on the fact if the user was adding a new record or updating an existing one.
Note that because <tt>atkNodeValidator::validateAttributeValue()</tt> specifically exempts empty fields from validation, a custom <tt>test_validate</tt> function cannot be used to check whether a field is empty--<tt>test_validate</tt> will never be called.  However, if you only want to ensure that a field is non-empty, you can use the <tt>AF_OBLIGATORY</tt> flag, as described above.  e.g.
<syntaxhighlight lang="php">
  public static function meta(atkMetaPolicy $policy)
  {
    $policy->setFlag('start_date', AF_OBLIGATORY);   
  }
</syntaxhighlight>


== Method 2. Overriding a node's validate method. ==
== Method 2. Overriding a node's validate method. ==
Line 31: Line 41:
Code:
Code:


  function validate(&$record, $mode)
<syntaxhighlight lang="php">
  {
public function validate(&$record, $mode)
     if ($record["skipvalidation"] == 1)
{
    {
     if ($record["skipvalidation"] == 1) {
      // do nothing, the user told us to not validate the record by
        // do nothing, the user told us to not validate the record by
      // putting our 'skipvalidation' field for this record to 1.
        // putting our 'skipvalidation' field for this record to 1.
      // (in a real world app, this would not make much sense, but it's
        // (in a real world app, this would not make much sense, but it's
      // ok as an example)
        // ok as an example)
     }
     } else {
    else
        // call original validation
    {
        parent::validate($record, $mode);
      // call original validation
      parent::validate($record, $mode);
     }
     }
   }
   }
</syntaxhighlight>


== Method 3. Custom attribute. ==
== Method 3. Custom attribute. ==
Line 53: Line 62:
Place the following for example in modules/mymod/attributes/class.codeattribute.inc:
Place the following for example in modules/mymod/attributes/class.codeattribute.inc:


 
<syntaxhighlight lang="php">
  <?php
<?php
    
    
    class codeAttribute extends atkAttribute
class codeAttribute extends atkAttribute
{
    public function validate(&$record, $mode)
     {
     {
      function validate(&$record, $mode)
         if (!$this->_isValidCode($record[$this->fieldName()])) {
      {
            atkTriggerError($record, $this, "not a valid code");
         if (!$this->isValidCode($record[$this->fieldName()]))
        {
          triggerError($record, $this->fieldName(), "not a valid code");
         }
         }
      }
    }
    
    
      function isValidCode($string)
    protected function _isValidCode($string)
      {
    {
         // your code validation here...
         // your code validation here...
         return true;
         return true;
      }
     }
     }
}
    
    
  ?>
</syntaxhighlight>


Then, in your node, it's a matter of:
Then, in your node, it's a matter of:


<syntaxhighlight lang="php">
   useattrib("mymod.codeattribute");
   useattrib("mymod.codeattribute");
   .....
   .....
    
    
   $this->add(new codeAttribute("identifier"));
   $this->add(new codeAttribute("identifier"));
</syntaxhighlight>


== Internationalising the error string ==
== Internationalising the error string ==
Line 86: Line 96:
If your app is multilingual, instead of passing an error message to triggerError, you can pass a language key, like this:
If your app is multilingual, instead of passing an error message to triggerError, you can pass a language key, like this:


<syntaxhighlight lang="php">
   triggerError($record, "field", "error_invalidcode");
   triggerError($record, "field", "error_invalidcode");
</syntaxhighlight>


Then, in your language files, add the key with the translation, like this:
Then, in your language files, add the key with the translation, like this:


<syntaxhighlight lang="php">
   "error_invalidcode"=>"The value is not a valid code"
   "error_invalidcode"=>"The value is not a valid code"
</syntaxhighlight>

Latest revision as of 13:24, 12 February 2010

ATK Howto: Custom Validation Logic

Complexity: Easy
Author: Ivo Jansch <ivo@achievo.org>

List of other Howto's

Intro

In an ATK application, there are several validations that the frameworks handles for you; you just need to specify certain flags like AF_UNIQUE or AF_OBLIGATORY. Also, there are attributes that do validation of the input data, such as the atkEmailAttribute, which will not allow the user to enter an invalid e-mail address.

There are times however, when you would want to add custom validation logic to your application. This howto presents 3 ways to do this.

Method 1. Validation of a single attribute

Suppose you have a field named 'test', here's how to create a validation method that is automatically fired whenever the user wants to save a record:

Code:

public function test_validate(&$record, $mode)
{
    if ($record["test"]!="something") {
        atkTriggerError($record, $this->getAttribute("test"), "Test field should be 'something'");
    }
}

This is the prefered way of adding custom validation to a node.

The $mode param is either 'add' or 'update', so you could do validation based on the fact if the user was adding a new record or updating an existing one.

Note that because atkNodeValidator::validateAttributeValue() specifically exempts empty fields from validation, a custom test_validate function cannot be used to check whether a field is empty--test_validate will never be called. However, if you only want to ensure that a field is non-empty, you can use the AF_OBLIGATORY flag, as described above. e.g.

  public static function meta(atkMetaPolicy $policy)
  {
    $policy->setFlag('start_date', AF_OBLIGATORY);     
  }

Method 2. Overriding a node's validate method.

If you need more flexibility, for example if you need to prevent the original validation of the data, you can completely override the node validate() method.

Code:

public function validate(&$record, $mode)
{
    if ($record["skipvalidation"] == 1) {
        // do nothing, the user told us to not validate the record by
        // putting our 'skipvalidation' field for this record to 1.
        // (in a real world app, this would not make much sense, but it's
        // ok as an example)
    } else {
        // call original validation
        parent::validate($record, $mode);
    }
  }

Method 3. Custom attribute.

Finally, if you need to reuse validation of fields in multiple nodes, it's best to create a custom attribute. For example, if you have a 'code' field for entering the code of a record, and there's some company standard for code fields you need to verify, you could create a custom attribute.

Place the following for example in modules/mymod/attributes/class.codeattribute.inc:

<?php
  
class codeAttribute extends atkAttribute
{
    public function validate(&$record, $mode)
    {
        if (!$this->_isValidCode($record[$this->fieldName()])) {
            atkTriggerError($record, $this, "not a valid code");
        }
    }
  
    protected function _isValidCode($string)
    {
        // your code validation here...
        return true;
    }
}

Then, in your node, it's a matter of:

  useattrib("mymod.codeattribute");
  .....
  
  $this->add(new codeAttribute("identifier"));

Internationalising the error string

If your app is multilingual, instead of passing an error message to triggerError, you can pass a language key, like this:

  triggerError($record, "field", "error_invalidcode");

Then, in your language files, add the key with the translation, like this:

  "error_invalidcode"=>"The value is not a valid code"