A free and open-source book on ZF3 for beginners


9.4. Instantiating a Validator

In Zend Framework 3, there are several methods of creating a validator:

Next, we will cover these three methods in more details.

9.4.1. Method 1. Manual Instantiation of a Validator

A validator in general can be used not only with forms, but also for validation of an arbitrary data. In order to do that, you simply create an instance of the validator class, configure the validator by using the methods it provides, and call the isValid() method on the validator.

For example, let's consider the usage of the EmailAddress validator which checks an E-mail address for conformance to RFC-2822 standard. An E-mail address typically consists of the local part (user name) followed by the "at" character (@), which is in turn followed by the host name. For example, in the "name@example.com" E-mail address, "name" is the local part, and "example.com" is the host name.

The EmailAddress validator is useful for checking an user-entered E-mail addresses on your forms for correctness. The validator will check for the correctness of the local part and the host name, for presence of the "at" character (@) and, optionally, will connect to the recipient's host and query the DNS service for existence of the MX (Mail Exchanger) record 30.

30) An MX record is a type of record used in the Domain Name System (DNS). MX records define one or several mail server addresses assigned to recipient's domain.

The methods provided by the EmailAddress validator are listed in table 9.2:

Table 9.2. Public methods of the EmailAddress validator
Method name Description
__construct($options) Constructs the validator. Accepts the list of options allowing to configure it.
isValid($value) Returns true if the value is a valid E-mail address according to RFC-2822; otherwise returns false.
getMessages() If validation failed, this method will return an array of error messages.
useDomainCheck($domain) Tells the validator to check the host name part for correctness.
getDomainCheck() Returns true if host name part check is enabled.
setHostnameValidator($hostnameValidator) Attaches the validator to use for checking host name part of the E-mail address.
getHostnameValidator() Returns the validator used for checking host name part of the E-mail address.
setAllow($allow) Sets the allowed types of host names to be used in an E-mail address.
getAllow() Returns the allowed types of host names.
useMxCheck($mx) Sets whether to perform the check for a valid MX record via DNS service.
getMxCheck($mx) Returns true if MX check mode is enabled.
useDeepMxCheck($deep) Sets whether to use deep validation for MX records.
getDeepMxCheck() Returns true if the deep MX check mode is enabled; otherwise returns false.
isMxSupported() Returns true if MX checking via getmxrr() PHP function is supported in the system; otherwise returns false.
getMXRecord() After validation, returns the found MX record information.

As you can see from the table, the EmailAddress validator, additionally to the isValid() and getMessages() methods, provides the constructor method to which you can (optionally) pass the complete list of options for initializing the validator.

All standard validators have the constructor method (optionally) accepting an array of options for configuring the validator when instantiating it manually.

The EmailAddress class also provides a number of methods that can be used for setting specific validator options.

The useDomainCheck() method tells whether to check the host name for correctness, or not. By default, this check is enabled. The setAllow() method provides an ability to specify which types of host names are allowed. You can pass an OR combination of the ALLOW_-prefixed constants 31 to the setAllow() method:

31) The ALLOW_-prefixed constants are provided by the Hostname validator.

Internally, the EmailAddress validator uses the Hostname validator for checking the host name part of an E-mail address. Optionally, you can attach a custom host name validator by using the setHostnameValidator() method, however it is unlikely you will need to do such.

The useMxCheck() method tells whether the validator should connect to the recipient's host and query the DNS server for the MX record(s). If the server has no MX records, than the validation fails. You can additionally use the useDeepMxCheck() method to tell the validator to compare the mail server addresses extracted from the MX records against the black list of reserved domain names, and perform additional checks per each detected address.

It is not recommended to perform MX check (and deep MX check), because that may take a lot of time and increase the web page load time. By default, these checks are disabled.

Below, we provide code examples showing two equivalent methods of manual creating of an instance of the EmailAddress validator, setting its options and checking an input value:

Example 1. Passing options to the constructor method.

<?php
// Optionally, define a short alias for the validator class name.
use Zend\Validator\EmailAddress;
use Zend\Validator\Hostname;

// Create an instance of the validator, passing options to the constructor.
$validator = new EmailAddress([
		'allow' => Hostname::ALLOW_DNS|Hostname::ALLOW_IP|Hostname::ALLOW_LOCAL,
		'mxCheck' => true,
		'deepMxCheck' => true
	]);

// Validate an E-mail address.
$isValid = $validator->isValid('name@example.com'); // Returns true.
$isValid2 = $validator->isValid('abc'); // Returns false.

if(!$isValid2) {
  // Get error messages in case of validation failure.
  $errors = $validator->getMessages();
}

In the code above, we create the EmailAddress validator object with the help of the new operator (line 7). We pass the array of options to the constructor. We use the allow key to allow an E-mail address to be a domain name, an IP address or local network address. Also, we use the mxCheck and deepMxCheck to enable MX record check and deep MX record check, respectively.

In line 14, we call the isValid() method and pass it the string value "name@example.com" to be checked. The expected output of this call is the boolean true.

In line 15, we pass the "abc" string value to the validator. The validation procedure is expected to fail (false is returned). Then, the error messages are retrieved with the getMessages() method (line 19).

Example 2. Without passing options to the constructor.

<?php
// Optionally, define a short alias for the validator class name.
use Zend\Validator\EmailAddress;
use Zend\Validator\Hostname;

// Create an instance of the validator.
$validator = new EmailAddress();

// Optionally, configure the validator
$validator->setAllow(
       Hostname::ALLOW_DNS|Hostname::ALLOW_IP|Hostname::ALLOW_LOCAL);
$validator->useMxCheck(true);
$validator->useDeepMxCheck(true);

// Validate an E-mail address.
$isValid = $validator->isValid('name@example.com'); // Returns true.
$isValid2 = $validator->isValid('abc'); // Returns false.

if(!$isValid2) {
  // Get error messages in case of validation failure.
  $errors = $validator->getMessages();
}

In the code above, we create the EmailAddress validator object with the help of the new operator (line 7).

In lines 10-13, we configure the validator. We call the setAllow() method to allow an E-mail address to be a domain name, an IP address or local network address. Also, we use the useMxCheck() and useDeepMxCheck() to enable MX record check and deep MX record check, respectively.

In line 16, we call the isValid() method and pass it the string value "name@example.com" to be checked. The expected output of this call is the boolean true.

In line 17, we pass the "abc" string value to the validator. The validation procedure is expected to fail. Then, the error messages are retrieved with the getMessages() method (line 21).

9.4.2. Method 2. Using StaticValidator Wrapper

An alternative way of manual validator instantiation is by using the StaticValidator class. The StaticValidator class is some kind of a "proxy" designed for automatic validator instantiation, configuration and execution. For example, let's consider how to create the same EmailAddress validator, configure it and call its isValid() method:

<?php
// Create and execute the EmailAddress validator through StaticValidator proxy.
$validatedValue = \Zend\Validator\StaticValidator::execute('name@example.com', 
                    'EmailAddress', 
                    [
                      'allow' => 
                         Hostname::ALLOW_DNS|
                         Hostname::ALLOW_IP|
                         Hostname::ALLOW_LOCAL,
                      'mxCheck' => true,
                      'deepMxCheck' => true
                    ]);
						
// The expected output is boolean true.

The StaticValidator class provides the execute() static method which takes three arguments: the input value, the name of the filter to apply, and the array of filter-specific options.

In line 3, we call the execute() method to automatically create the EmailAddress validator, call its setAllowDns(), useMxCheck() and useDeepMxCheck() methods, and pass the input value to its isValid() method. This is very useful, because can be accomplished in a single call.

The StaticValidator doesn't provide an ability to extract the list of human-readable validation errors. However, since the StaticValidator is designed to be used outside forms, and not intended for displaying results to a human, this seems to be not a big disadvantage.

9.4.3. Method 3. Using an Array Configuration

When using validators with form's validation rules, you typically do not construct a validator object explicitly as we did in the previous section, instead you pass an array configuration to the factory class which automatically constructs the validator for you and (optionally) configures it. We already saw how this works when adding validation rules for the feedback form in Collecting User Input with Forms.

For example, let's show how to construct the same EmailAddress filter with the help of the factory:

<?php
// It is assumed that you call the following code inside of the form model's
// addInputFilter() method.

$inputFilter->add([
  // ...  
  'validators'  => [
    [
      'name' => 'EmailAddress',
      'options' => [
        'allow' => \Zend\Validator\Hostname::ALLOW_DNS,
        'useMxCheck' => false,
        'useDeepMxCheck' => false,
      ],
    ],
  ],                
  // ...
]);

In the code above, we call the add() method provided by the InputFilter container class (line 5). The add() method takes an array which has the validators key. You typically register the validators under that key (line 7). Validators registered under that key are inserted into validator chain in the order they appear in the list.

A validator configuration typically consists of the name (line 9) and options (line 10). The name is a fully qualified validator class name (e.g. \Zend\Validator\EmailAddress) or its short alias (EmailAddress). The options is an array consisting of validator-specific options. When the factory class instantiates the validator, it passes the list of options to the validator's constructor, and the constructor initializes the validator as needed.


Top