Deprecated/0.11.0/Validation

Warning! This page has the following tags:

  • This page is deprecated as of Agavi 0.11.0, but still contains useful information.
  • This page needs to be fixed and then merged with docbook documentation.

Validation

Validation is completly rewritten in Agavi 0.11. This doc tries to describe some of the new concepts and features.

config files

The validation system uses XML files to configure how the input is validates. The format of these files is not fixed yet but is likely to look something like this:

<?xml version="1.0" encoding="UTF-8"?>

<configurations>
  <configuration>
    <validators>

      <validator class="string" name="val_username">
        <parameters>
          <parameter name="param">username</parameter>
          <parameter name="min">5</parameter>
          <parameter name="min_error">string is too short</parameter>
        </parameters>
      </validator>

      <validator class="or">
        <validators>
          <validator class="equals" name="val_eq_username" severity="none">
            <parameters>
              <parameter name="param">username</parameter>
              <parameter name="value">admin</parameter>
            </parameters>
          </validator>

          <validator class="string" name="val_passlen" error="password too short">
            <parameters>
              <parameter name="param">password1</parameter>
              <parameter name="min">8</parameter>
            </parameters>
          </validator>
        </validators>
      </validator>

      <validator class="equals" name="val_samepasses" error="passwords do not match">
        <parameters>
          <parameter name="value">password2</parameter>
          <parameter name="asparam">1</parameter>
        </parameters>
      </validator>

    </validators>
  </configuration>
</configurations>

The above file validates a form consisting of 3 input fields: username, password1 and password2. Its a registration form in which you have to put a preferred username and a valid password. That means a password at least 8 characters long. There is one exception from this rule: When you choose the username "admin", there should be no restriction about the length of the password. (It's a stupid example but it's only an example.) To verify the password you have to put it in each of the password fields.

Now lets see, how the validation processes. The first validator is a string-validator (class="string") named "val_username". It takes the input in the field "username" (see parameter named 'param') and checks the length (see parameter 'min'). If the string is shorter then 5 characters, the error in parameter 'min_error' is submitted.

Next validator is an operator. Operators are special validators because they have one or more child validators and their result is calculated from the results of these child validators. There are 4 Operators defined: AND, OR, XOR and NOT. They represent their meaning as boolean operators. In our example the or operator means, that if only one of the two child validators succeeds then the operator reports a successful validation. (More about the function of operators in section 'operators')

First the equals-validator named "val_eq_username" is processed. If the username equals to 'admin' then the operator succeeds and the other validator inside of the operator is skipped. (for informations about the severity="none" attribute see section 'error severities') Otherwise the password in field "password1" is checked, whether it is at least 8 characters long.

The last validator is again an equals-validator. But this time it does not check against a fixed value but another input. The parameter 'asparam' tells the validator not to check against the value of parameter named 'value' but the content of an input field with that name.

In the end we get a result that says whether the form passed the validation system or not. To learn how to fetch the error messages that where thrown in the process see section 'fetching errors'.

error severities

There are 3 error severities with different meanings to the further validation process:

CRITICAL

The validation process is aborted immediately. You can use this severity for input fields that are so important that if they fail there is no need to validate the rest of the input.

ERROR

This is the standard severity. The errors renders the whole validation process as failed but goes on checking the rest of the form. This way you are able to show the user a form with a collection of errors he/she made so the can correct all of them in one step.

NONE

This severity is usefull in operators as it reports the validator as failed but does not renders the whole validation process as a failure.

SUCCESS

The result means that the validator succeeded.

usage

By default the compiler puts a severity of "ERROR" into to validators unless there is a attribute named "severity" specified. In this case the given severity is used for the validator.

fetching errors

There are two ways to fetch the errors of the validation process. The first array, returned by getErrorArrayByValidator(), is sorted by validator names and has the following format:

array(
   validatorName => array(
      'error'  => error,
      'fields' => array of field names
   )
)
validatorName
name of the validator that failed
error
error message (type mixed so does not need to be a string)
array of field names
fieds that were affected by this validator (mostly the field in parameter 'param' or the fields listed in parameter 'affects')

The other format is sorted by input fields and is returned by getErrorArrayByInput(). It has following format:

array(
   fieldName => array(
      'message'    => error message,
      'validators' => array(
         validatorName => error
      )
)
fieldName
name of field that did not pass the validation
error message
first type string error value reported related to this field
validatorName
name of the validator that failed
error
error value that was submitted by the validator

In addition to these two methods there are two other methods on AgaviValidatorManager:

getErrorMessage()
returns the first submitted error value of type string
getResult()
returns the highest error severity that was submitted (see error severity constants in AgaviValidator) or 0 (which is constant SUCCESS in AgaviValidator) for success

operators

As mentioned in the example in the first section, operators are special validators because they have child validators. To calculate there validation result, they process there child validators and combine these results according to the meaning of their corresponding boolean operators.

child validators

The AND and OR operators can have an unlimited amough of child validators. To speed up validation the processing of child validators stops at once the result is clear. That means after the first success in OR or at first failure in AND. This is controlled by the parameter 'break' which defaults to true. If you wish to process all children even if the result is fixed already, set 'break' to false.

The XOR and NOT operators need a specific amough of child validators to work. This is one child validator for the NOT operator and two for XOR. Not following this restriction results in a thrown exception in the validator so beware of messing up your config.

Dependencies

The dependencies provide a possibility to validate a bunch of input fields in relation to the results of other validators. Each validator can specify a list of dependencies that have to be met to process the validation. If even one of the dependencies is not met, the validor is not executed and returns with a sucessful result. On the other side, a validator can set a list of dependencies that should be seen as provided when the validation succeeded.

Dependencies are set in the following attributes in the config file:

depends
comma seperated list of dependency tokens that need to be defined before by other validators
provides
tokens that are to be defined after successful validation

exporting data

Validators can export data back into the request. This can be useful if you validate an input with several possible formats and want to convert the input into a specific standard format to work with it later. The name of the index into which the data should be exported into the request is set in the parameter 'export'.

validation of arrays

paths

Paths are just a different way of addressing a value in an array. Instead of writing something like $array['index1'][3]['index3'] you could write /array/index1/3/index3. You can compare arrays with filesystems where arrays are the directories and the scalar values are the files.

Also possible are '..'-directories. The path /array/index1/3/../2/index3/../../4/index4 is the same as $array[index1][4][index4].

example

Take we have a form like this:

<form action... blabla>
   <input type="text" name="date[][date]" value="">
   <input type="text" name="date[][date]" value="">
   <input type="text" name="date[][date]" value="">
   <input type="text" name="date[][date]" value="">
   <input type="text" name="date[][date]" value="">
</form>

Now we could define 5 validators for checking each of the input fields but that's not really appropriate. Insteat we define the following validator:

<validator class="date" name="dateval" error="invalid date" base="/date/*" depends="/globaldep,localdep">
   <parameters>
      <parameter name="param">date</parameter>
   </parameters>
</validator>

The interesting parameter in this config is the 'base' parameter. It sets the base path of all input names, dependency tokens and the name of the validator. You can see the base as some kind of 'current working directory'. As you can see, you are able put wildcards in the path just like in a real filesystem. These wildcards get expanded by the available index names at this position in the request array.

NOTE: currently wildcards are only expanded in the parameter 'base' so all the names in 'param' etc. have to be relativ to this base.

When the validator is executed, it becames aware of the base and the wildcard in the path. After expanding there are 5 'real' base paths and therefore 5 values to validate. So the actual validation is done for all 5 values.

Like in 'single mode' first the dependencies are checked. After combining them with the base, we have two dependencies, that have to be met: /globaldep and /date/x/localdep (where x is the current index). You can see that the slash at the beginning of '/globaldep' forms that token into an absolute path (again the reference to filesystems). This way you can manage some kind of global dependencies that are provided by total independent validators and local dependencies that come from validators that share some parts of validators own base path.

To fetch the input value, the name in 'param' is appended to the base and this path is used to fetch the value from the request. If the validation fails and an error has to be submitted, the base is used again to form an 'absolute' validator name. After the error was sent to the error manager, the validator returns with the corresponding error code.

another example

Another form of arrays that can be validated are like $date[]. In this case the wildcard is the last component of the path. So the validator would look like this:

<validator class="date" name="dateval" error="invalid date" base="/date/*" depends="/globaldep,localdep">
   <parameters>
      <parameter name="param"></parameter>
   </parameters>
</validator>

Again the base of the validator is '/date/*' but this time the 'param' is empty. This does not mean that no input is validated. Remember that before fetching the data, the name is appended to the base so we get '/date/x' (where x is the current index) and that is exactly where our input is saved.

TODO

Currently there is a limitation that wildcards are only expanded in the parameter 'base'. Later there will be support for putting wildcards directly into 'param' or other parameters.

writing your own validator

validation of uploaded files