A free and open-source book on ZF3 for beginners

Translation into this language is not yet finished. You can help this project by translating the chapters and contributing your changes.

8.7. Escribir nuestro propio filtro

Una alternativa al uso del filtro Callback es escribir nuestra propia clase filtro implementando la interfaz FilterInterface. Este filtro se puede usar en los formularios de la aplicación web o si lo deseamos fuero del formulario.

Para demostrar como crear nuestro propio filtro escribiremos la clase PhoneFilter que encapsula el algoritmo de filtrado de número de teléfonos que usamos en el ejemplo del filtro Callback.

Como podemos recordar, la clase concreta base para todos los filtros estándares es la clase AbstractFilter. Por analogía, también derivaremos nuestro filtro personalizado PhoneFilter de la clase base.

Planeamos tener los siguientes métodos en nuestra clase filtro PhoneFilter (ver tabla 8.18):

Tabla 8.18. Métodos públicos del filtro PhoneFilter
Nombre del método Descripción
__construct($options) Constructor. Acepta opcionalmente el argumento $options que se usa para asignar las opciones del filtro de una vez.
setFormat($format) Asigna la opción de formato de número.
getFormat() Regresa la opción de formato de número.
filter($value) Ejecuta el filtro de teléfono.

Para comenzar, creamos el archivo PhoneFilter.php en la carpeta Filter dentro de la carpeta fuente del módulo 28. Luego, colocamos el siguiente código dentro del archivo:

28) La clase PhoneFilter se puede considerar como un modelo de servicio porque su objetivo es procesar datos, no guardarlos. Por convención, guardamos todos los filtros personalizados dentro de la carpeta Filter.

<?php
namespace Application\Filter;

use Zend\Filter\AbstractFilter;

// This filter class is designed for transforming an arbitrary phone number to
// the local or the international format.
class PhoneFilter extends AbstractFilter
{
  // Phone format constants.
  const PHONE_FORMAT_LOCAL = 'local'; // Local phone format
  const PHONE_FORMAT_INTL  = 'intl';  // International phone format

  // Available filter options.
  protected $options = [
    'format' => self::PHONE_FORMAT_INTL
  ];

  // Constructor.
  public function __construct($options = null)
  {
    // Set filter options (if provided).
    if(is_array($options)) {

      if(isset($options['format']))
        $this->setFormat($options['format']);
    }
  }

  // Sets phone format.
  public function setFormat($format)
  {
    // Check input argument.
    if( $format!=self::PHONE_FORMAT_LOCAL &&
       $format!=self::PHONE_FORMAT_INTL ) {
      throw new \Exception('Invalid format argument passed.');
    }

    $this->options['format'] = $format;
  }

  // Returns phone format.
  public function getFormat()
  {
    return $this->format;
  }

  // Filters a phone number.
  public function filter($value)
  {
    if(!is_scalar($value)) {
      // Return non-scalar value unfiltered.
      return $value;
    }

    $value = (string)$value;

    if(strlen($value)==0) {
      // Return empty value unfiltered.
      return $value;
    }

    // First, remove any non-digit character.
    $digits = preg_replace('#[^0-9]#', '', $value);

    $format = $this->options['format'];

    if($format == self::PHONE_FORMAT_INTL) {
      // Pad with zeros if the number of digits is incorrect.
      $digits = str_pad($digits, 11, "0", STR_PAD_LEFT);

      // Add the braces, the spaces, and the dash.
      $phoneNumber = substr($digits, 0, 1) . ' (' .
                     substr($digits, 1, 3) . ') ' .
                     substr($digits, 4, 3) . '-' .
                     substr($digits, 7, 4);
    } else { // self::PHONE_FORMAT_LOCAL
      // Pad with zeros if the number of digits is incorrect.
      $digits = str_pad($digits, 7, "0", STR_PAD_LEFT);

      // Add the dash.
      $phoneNumber = substr($digits, 0, 3) . '-'. substr($digits, 3, 4);
    }

    return $phoneNumber;
  }
}

En la línea 2 podemos ver que la clase filtro está en el espacio de nombres Application\Filter.

En la línea 8 definimos la clase PhoneFilter. Derivamos nuestra clase filtro de la clase base AbstractFilter para reusar las funcionalidades que provee. La línea 4 contiene el alias de la clase AbstractFilter.

En las líneas 11-12, por convención, definimos los formatos de número de teléfono como constantes (PHONE_FORMAT_INTL para el formato internacional y PHONE_FORMAT_LOCAL para el formato local). Estos son respectivamente los equivalentes de «intl» y «local».

En las líneas 15-17, definimos la variable privada $options que es un arreglo que tiene una sola llave llamada «format». Esta llave contiene la opción de formato del número de teléfono para nuestro filtro.

En las líneas 20-28, tenemos el método constructor que solamente toma el argumento $options. Cuando construimos el filtro manualmente podemos omitir este parámetro. Sin embargo, cuando el filtro es construido por la clase fábrica, la fábrica pasará las opciones del filtro al constructor del filtro por medio de este argumento.

En las líneas 31-40 y 43-46 tenemos los métodos setFormat() y getFormat() que permiten respectivamente colocar y recuperar el formato del número de teléfono.

En las líneas 49-86 está el método filter(). Este método encapsula el algoritmo que filtra el número de teléfono. El método toma el parámetro $value transformándolo de acuerdo con el formato del número telefónico seleccionado y regresándolo formateado.

8.7.1. Uso de la clase PhoneFilter

Cuando la clase filtro PhoneFilter está lista podemos fácilmente comenzar a usarla en el formulario de contacto (o en otro formulario) de la siguiente manera. Estamos suponiendo que llamamos el siguiente código dentro del método ContactForm::addInputFilter():

$inputFilter->add([
      'name'     => 'phone',
      'required' => true,
      'filters'  => [
        [
          'name' => PhoneFilter::class,
          'options' => [
            'format' => PhoneFilter::PHONE_FORMAT_INTL
          ]
        ],
        // ...
      ],
      // ...
    ]);

Podemos ver como el filtro PhoneFilter trabaja en el ejemplo Form Demo, la aplicación de ejemplo que está junto a este libro. Abrimos la página «http://localhost/contactus» en nuestro navegador web. Si ingresamos algún número de teléfono en un formato incorrecto el filtro corregirá el número de teléfono.

Si lo deseamos podemos usar la clase PhoneFilter fuera de los formularios como se muestra más abajo:

<?php
use Application\Filter\PhoneFilter;

// Create PhoneFilter filter.
$filter = new PhoneFilter();

// Configure the filter.
$filter->setFormat(PhoneFilter::PHONE_FORMAT_INTL);

// Filter a string.
$filteredValue = $filter->filter('12345678901');

// The expected filter's output is the '1 (234) 567-8901'.

Top