Zend_Filter_Input proporciona una interfaz declarativa para asociar
múltiples filtros y validadores, aplicarlos a colecciones de datos, y
recuperar los valores de entrada una vez que han sido procesados por los filtros
y validadores. Los valores se devuelven en formato escapado por defecto para
una salida segura en HTML.
Considere la metáfora de que esta clase es una jaula para datos externos. Los datos entran en la aplicación desde fuentes externas, como parámetros de peticiones HTTP, cabeceras HTTP, un servicio web, o incluso se leen desde una base de datos u otro archivo. Los datos se colocan primero en la jaula, y posteriormente la aplicación solo puede acceder a los datos indicando a la jaula qué deben ser los datos y cómo planean usarlos. La jaula inspecciona los datos para comprobar su validez. Puede aplicar escapado a los valores de datos para el contexto apropiado. La jaula libera los datos solo si puede cumplir con estas responsabilidades. Con una interfaz simple y conveniente, esto fomenta buenos hábitos de programación y hace que los desarrolladores piensen en cómo se usan los datos.
Los filtros transforman valores de entrada, eliminando o cambiando caracteres dentro del valor. El objetivo es "normalizar" los valores de entrada hasta que coincidan con un formato esperado. Por ejemplo, si se necesita una cadena de dígitos numéricos, y el valor de entrada es "abc123", entonces podría ser una transformación razonable cambiar el valor a la cadena "123".
Los validadores comprueban los valores de entrada contra criterios e informan si pasaron la prueba o no. El valor no se cambia, pero la comprobación puede fallar. Por ejemplo, si una cadena debe parecerse a una dirección de correo electrónico, y el valor de entrada es "abc123", entonces el valor no se considera válido.
Los escapadores transforman un valor eliminando el comportamiento mágico de ciertos caracteres. En algunos contextos de salida, los caracteres especiales tienen significado. Por ejemplo, los caracteres '<' y '>' delimitan etiquetas HTML, y si una cadena que contiene esos caracteres se emite en un contexto HTML, el contenido entre ellos podría afectar la salida o funcionalidad de la presentación HTML. Escapar los caracteres elimina el significado especial, de modo que se emiten como caracteres literales.
Para usar Zend_Filter_Input, realice los siguientes pasos:
Declarar reglas de filtro y validador
Crear el procesador de filtros y validadores
Proporcionar los datos de entrada
Recuperar los campos validados y otros informes
Las siguientes secciones describen los pasos para usar esta clase.
Antes de crear una instancia de Zend_Filter_Input, declare un
array de reglas de filtro y un array de reglas de validador.
Este array asociativo asigna un nombre de regla a un filtro o
validador o a una cadena de filtros o validadores.
El siguiente ejemplo declara un conjunto de reglas de filtro donde el campo
'month' se filtra con Zend_Filter_Digits, y el campo
'account' se filtra con Zend_Filter_StringTrim. Luego un
conjunto de reglas de validación declara que el campo 'account' es válido solo si contiene
únicamente caracteres alfabéticos.
$filters = array(
'month' => 'Digits',
'account' => 'StringTrim'
);
$validators = array(
'account' => 'Alpha'
);
Cada clave en el array $filters anterior es el nombre de una regla para
aplicar un filtro a un campo de datos específico. Por defecto, el nombre de la regla
es también el nombre del campo de datos de entrada al que se aplica la regla.
Puede declarar una regla en varios formatos:
-
Un único escalar de tipo cadena, que se asigna a un nombre de clase.
$validators = array( 'month' => 'Digits', ); -
Una instancia de objeto de una de las clases que implementan
Zend_Filter_InterfaceoZend_Validate_Interface.$digits = new Zend_Validate_Digits(); $validators = array( 'month' => $digits ); -
Un array, para declarar una cadena de filtros o validadores. Los elementos de este array pueden ser cadenas que se asignan a nombres de clase u objetos filtro/validador, como en los casos descritos anteriormente. Además, puede usar una tercera opción: un array que contiene una cadena que se asigna al nombre de la clase seguida de los argumentos que se pasan a su constructor.
$validators = array( 'month' => array( 'Digits', // string new Zend_Validate_Int(), // object instance array('Between', 1, 12) // string with constructor arguments ) );
![]() |
Nota |
|---|---|
Si declara un filtro o validador con argumentos de constructor en un array, entonces debe crear un array para la regla, incluso si la regla tiene solo un filtro o validador. |
Puede usar una clave de regla especial "comodín" '*' en el array de filtros o en el array de validadores. Esto significa que los filtros o validadores declarados en esta regla se aplicarán a todos los campos de datos de entrada. Tenga en cuenta que el orden de las entradas en el array de filtros o de validadores es significativo; las reglas se aplican en el mismo orden en que las declara.
$filters = array(
'*' => 'StringTrim',
'month' => 'Digits'
);
Después de declarar los arrays de filtros y validadores, úselos como
argumentos en el constructor de Zend_Filter_Input. Esto devuelve
un objeto que conoce todas sus reglas de filtrado y validación, y usted
puede usar este objeto para procesar uno o más conjuntos de datos de entrada.
$input = new Zend_Filter_Input($filters, $validators);
Puede especificar los datos de entrada como tercer argumento del constructor. La
estructura de datos es un array asociativo. Las claves son nombres de campos,
y los valores son valores de datos. Las variables superglobales estándar $_GET
y $_POST de PHP son
ejemplos de este formato. Puede usar cualquiera de estas variables como datos
de entrada para Zend_Filter_Input.
$data = $_GET; $input = new Zend_Filter_Input($filters, $validators, $data);
De forma alternativa, use el método setData(), pasando
un array asociativo de pares clave/valor con el mismo formato
descrito anteriormente.
$input = new Zend_Filter_Input($filters, $validators); $input->setData($newData);
El método setData() redefine los datos en un objeto
Zend_Filter_Input existente sin cambiar las reglas de filtrado y
validación. Usando este método, puede ejecutar las mismas reglas
contra distintos conjuntos de datos de entrada.
Después de haber declarado los filtros y validadores y creado el procesador de entrada, puede recuperar informes de campos faltantes, desconocidos e inválidos. También puede obtener los valores de los campos después de que se hayan aplicado los filtros.
Si todos los datos de entrada pasan las reglas de validación, el
método isValid() devuelve TRUE.
Si algún campo es inválido o falta algún campo requerido,
isValid() devuelve FALSE.
if ($input->isValid()) {
echo "OK\n";
}
Este método acepta un argumento de cadena opcional, que nombra
un campo individual. Si el campo especificado pasó la validación
y está listo para su recuperación, isValid('fieldName')
devuelve TRUE.
if ($input->isValid('month')) {
echo "Field 'month' is OK\n";
}
Los campos inválidos son aquellos que no pasan una o más de sus comprobaciones de validación.
Los campos faltantes son aquellos que no están presentes en los datos de entrada, pero que fueron declarados con el metacomando 'presence'=>'required' (vea la sección posterior sobre metacomandos).
Los campos desconocidos son aquellos que no están declarados en ninguna regla del array de validadores, pero que aparecen en los datos de entrada.
if ($input->hasInvalid() || $input->hasMissing()) {
$messages = $input->getMessages();
}
// getMessages() simply returns the merge of getInvalid() and
// getMissing()
if ($input->hasInvalid()) {
$invalidFields = $input->getInvalid();
}
if ($input->hasMissing()) {
$missingFields = $input->getMissing();
}
if ($input->hasUnknown()) {
$unknownFields = $input->getUnknown();
}
El resultado del método getMessages() es un
array asociativo, que asigna un nombre de regla a un array de mensajes de
error relacionados con esa regla. Tenga en cuenta que el índice de este
array es el nombre de regla usado en la declaración de la regla, que puede
ser diferente de los nombres de los campos comprobados por la regla.
El método getMessages() devuelve la combinación de los
arrays devueltos por getInvalid() y
getMissing(). Estos métodos devuelven subconjuntos de los
mensajes, relacionados con fallos de validación, o campos que fueron
declarados como requeridos pero faltan en la entrada.
El método getErrors() devuelve un array asociativo,
que asigna un nombre de regla a un array de identificadores de error. Los identificadores
de error son cadenas fijas, para identificar el motivo de un fallo
de validación, mientras que los mensajes pueden personalizarse.
Vea este capítulo para
más información.
Puede especificar el mensaje devuelto por
getMissing() usando la opción 'missingMessage',
como argumento del constructor de Zend_Filter_Input o usando
el método setOptions().
$options = array(
'missingMessage' => "Field '%field%' is required"
);
$input = new Zend_Filter_Input($filters, $validators, $data, $options);
// alternative method:
$input = new Zend_Filter_Input($filters, $validators, $data);
$input->setOptions($options);
Y también puede añadir un traductor que le da la capacidad de proporcionar múltiples
idiomas para los mensajes devueltos por
Zend_Filter_Input.
$translate = new Zend_Translate_Adapter_Array(array(
'content' => array(
Zend_Filter_Input::MISSING_MESSAGE => "Where is the field?"
)
);
$input = new Zend_Filter_Input($filters, $validators, $data);
$input->setTranslator($translate);
Cuando usa un traductor de ámbito de aplicación, este también será usado por
Zend_Filter_Input. En este caso no tendrá que establecer el
traductor manualmente.
El resultado del método getUnknown() es un
array asociativo, que asigna nombres de campos a valores de campos. Los nombres
de campo se usan como claves del array en este caso, en lugar de nombres de
regla, porque ninguna regla menciona los campos considerados
desconocidos.
Todos los campos que no son inválidos, faltantes ni desconocidos se
consideran válidos. Puede obtener los valores de los campos válidos usando un
accesor mágico. También hay métodos accesores no mágicos
getEscaped() y getUnescaped().
$m = $input->month; // escaped output from magic accessor
$m = $input->getEscaped('month'); // escaped output
$m = $input->getUnescaped('month'); // not escaped
Por defecto, al recuperar un valor, se filtra con
Zend_Filter_HtmlEntities. Esto es así por defecto porque se
considera el uso más común mostrar el valor de un campo
en HTML. El filtro HtmlEntities ayuda a evitar la salida no
intencionada de código, lo que puede provocar problemas de seguridad.
![]() |
Nota |
|---|---|
Como se muestra arriba, puede recuperar el valor sin escapar usando
el método |
![]() |
Escapado de campos no validados |
|---|---|
|
Como se mencionó antes,
$validators = array('*' => array());
$input = new Zend_Filter_Input($filters, $validators, $data, $options);
Pero tenga en cuenta que usar esta notación introduce una brecha de seguridad que podría usarse para ataques de cross-site scripting. Por lo tanto, siempre debería establecer validadores individuales para cada campo. |
Puede especificar un filtro diferente para escapar los valores, especificándolo en el array de opciones del constructor:
$options = array('escapeFilter' => 'StringTrim');
$input = new Zend_Filter_Input($filters, $validators, $data, $options);
Alternativamente, puede usar el método
setDefaultEscapeFilter():
$input = new Zend_Filter_Input($filters, $validators, $data); $input->setDefaultEscapeFilter(new Zend_Filter_StringTrim());
En cualquiera de los dos usos, puede especificar el filtro de escape como un nombre
base de cadena de la clase de filtro, o como una instancia de objeto de una clase
de filtro. El filtro de escape puede ser una instancia de una cadena de
filtros, un objeto de la clase Zend_Filter.
Los filtros para escapar la salida deben ejecutarse de esta manera, para
asegurarse de que se ejecutan después de la validación. Otros filtros que declare en
el array de reglas de filtro se aplican a los datos de entrada antes de que los datos
sean validados. Si los filtros de escape se ejecutaran antes de la validación,
el proceso de validación sería más complejo, y sería
más difícil proporcionar tanto la versión escapada como la sin escapar de los
datos. Por lo tanto, se recomienda declarar los filtros para escapar la salida
usando setDefaultEscapeFilter(), no en el
array $filters.
Solo hay un método getEscaped(), y
por lo tanto solo puede especificar un filtro para el escapado
(aunque este filtro puede ser una cadena de filtros). Si necesita que una
única instancia de Zend_Filter_Input devuelva una salida escapada
usando más de un método de filtrado, debería extender
Zend_Filter_Input e implementar nuevos métodos en su subclase
para obtener valores de diferentes formas.
Además de declarar la correspondencia entre campos y filtros
o validadores, puede especificar algunos "metacomandos" en las declaraciones
de los arrays, para controlar algún comportamiento opcional de
Zend_Filter_Input. Los metacomandos aparecen como entradas
indexadas por cadena en un valor de array de filtro o validador dado.
Si el nombre de la regla para un filtro o validador es diferente del campo al que debería aplicarse, puede especificar el nombre del campo con el metacomando 'fields'.
Puede especificar este metacomando usando la constante de clase
Zend_Filter_Input::FIELDS en lugar de la
cadena.
$filters = array(
'month' => array(
'Digits', // filter name at integer index [0]
'fields' => 'mo' // field name at string index ['fields']
)
);
En el ejemplo anterior, la regla de filtro aplica el filtro 'digits' al campo de entrada llamado 'mo'. La cadena 'month' simplemente se convierte en una clave mnemotécnica para esta regla de filtrado; no se usa como el nombre del campo si el campo se especifica con el metacomando 'fields', pero se usa como el nombre de la regla.
El valor por defecto del metacomando 'fields' es el índice de la regla actual. En el ejemplo anterior, si el metacomando 'fields' no se especifica, la regla se aplicaría al campo de entrada llamado 'month'.
Otro uso del metacomando 'fields' es especificar campos
para filtros o validadores que requieren múltiples campos como
entrada. Si el metacomando 'fields' es un array, el argumento
al filtro o validador correspondiente es un array de los
valores de esos campos. Por ejemplo, es común que los usuarios
especifiquen una cadena de contraseña en dos campos, y deben escribir la
misma cadena en ambos campos. Suponga que implementa una clase
validadora que toma un argumento de tipo array, y devuelve
TRUE si todos los valores del array son iguales entre
sí.
$validators = array(
'password' => array(
'StringEquals',
'fields' => array('password1', 'password2')
)
);
// Invokes hypothetical class Zend_Validate_StringEquals,
// passing an array argument containing the values of the two input
// data fields named 'password1' and 'password2'.
Si la validación de esta regla falla, la clave de la regla ('password') se usa en el
valor de retorno de getInvalid(), no ninguno de los campos nombrados
en el metacomando 'fields'.
Cada entrada en el array de validadores puede tener un metacomando llamado 'presence'. Si el valor de este metacomando es 'required' entonces el campo debe existir en los datos de entrada, o de lo contrario se informa como campo faltante.
Puede especificar este metacomando usando la constante de clase
Zend_Filter_Input::PRESENCE en lugar de la
cadena.
$validators = array(
'month' => array(
'digits',
'presence' => 'required'
)
);
El valor por defecto de este metacomando es 'optional'.
Si un campo no está presente en los datos de entrada, y especifica un valor para el metacomando 'default' de esa regla, el campo toma el valor del metacomando.
Puede especificar este metacomando usando la constante de clase
Zend_Filter_Input::DEFAULT_VALUE en lugar de la
cadena.
Este valor por defecto se asigna al campo antes de que se invoque ninguno de los validadores. El valor por defecto se aplica al campo solo para la regla actual; si el mismo campo se referencia en una regla posterior, el campo no tiene valor al evaluar esa regla. Por lo tanto, diferentes reglas pueden declarar diferentes valores por defecto para un campo dado.
$validators = array(
'month' => array(
'digits',
'default' => '1'
)
);
// no value for 'month' field
$data = array();
$input = new Zend_Filter_Input(null, $validators, $data);
echo $input->month; // echoes 1
Si su regla usa el metacomando FIELDS
para definir un array de múltiples campos, puede definir
un array para el metacomando DEFAULT_VALUE
y los valores por defecto de las claves correspondientes se usan para cualquier
campo faltante. Si FIELDS define múltiples
campos pero DEFAULT_VALUE es un escalar, entonces
ese valor por defecto se usa como valor para cualquier campo
faltante en el array.
No hay valor por defecto para este metacomando.
Por defecto, si un campo existe en los datos de entrada, entonces se aplican validadores al mismo, incluso si el valor del campo es una cadena vacía (''). Esto probablemente resulte en un fallo de validación. Por ejemplo, si el validador comprueba caracteres de dígito, y no hay ninguno porque una cadena de longitud cero no tiene caracteres, entonces el validador informa los datos como inválidos.
Si en su caso una cadena vacía debería considerarse válida, puede
establecer el metacomando 'allowEmpty' a TRUE.
Entonces los datos de entrada pasan la validación si están presentes en los
datos de entrada, pero tienen el valor de una cadena vacía.
Puede especificar este metacomando usando la constante de clase
Zend_Filter_Input::ALLOW_EMPTY en lugar de la
cadena.
$validators = array(
'address2' => array(
'Alnum',
'allowEmpty' => true
)
);
El valor por defecto de este metacomando es FALSE.
En el caso poco común en que declare una regla de validación sin
validadores, pero el metacomando 'allowEmpty' es
FALSE (es decir, el campo se considera inválido si
está vacío), Zend_Filter_Input devuelve un mensaje de error
por defecto que puede recuperar con getMessages(). Puede
especificar este mensaje usando la opción 'notEmptyMessage', como
argumento del constructor de Zend_Filter_Input o usando el
método setOptions().
$options = array(
'notEmptyMessage' => "A non-empty value is required for field '%field%'"
);
$input = new Zend_Filter_Input($filters, $validators, $data, $options);
// alternative method:
$input = new Zend_Filter_Input($filters, $validators, $data);
$input->setOptions($options);
Por defecto, si una regla tiene más de un validador, todos los validadores se aplican a la entrada, y los mensajes resultantes contienen todos los mensajes de error causados por la entrada.
Alternativamente, si el valor del metacomando 'breakChainOnFailure'
es TRUE, la cadena de validadores termina después de que falle
el primer validador. Los datos de entrada no se comprueban contra los
validadores posteriores en la cadena, por lo que podría causar más
violaciones incluso si corrige la que se informó.
Puede especificar este metacomando usando la constante de clase
Zend_Filter_Input::BREAK_CHAIN en lugar de la
cadena.
$validators = array(
'month' => array(
'Digits',
new Zend_Validate_Between(1,12),
new Zend_Validate_GreaterThan(0),
'breakChainOnFailure' => true
)
);
$input = new Zend_Filter_Input(null, $validators);
El valor por defecto de este metacomando es FALSE.
La clase de cadena de validadores, Zend_Validate, es más flexible
con respecto a la interrupción de la ejecución de la cadena que
Zend_Filter_Input. Con la primera clase, puede establecer la
opción de interrumpir la cadena al fallar de forma independiente para cada validador de la cadena.
Con la segunda clase, el valor definido del metacomando
'breakChainOnFailure' para una regla se aplica de manera uniforme
a todos los validadores de la regla. Si requiere el uso más
flexible, debería crear usted mismo la cadena de validadores,
y usarla como objeto en la definición de la regla de
validador:
// Create validator chain with non-uniform breakChainOnFailure
// attributes
$chain = new Zend_Validate();
$chain->addValidator(new Zend_Validate_Digits(), true);
$chain->addValidator(new Zend_Validate_Between(1,12), false);
$chain->addValidator(new Zend_Validate_GreaterThan(0), true);
// Declare validator rule using the chain defined above
$validators = array(
'month' => $chain
);
$input = new Zend_Filter_Input(null, $validators);
Puede especificar mensajes de error para cada validador en una regla usando el metacomando 'messages'. El valor de este metacomando varía según si tiene múltiples validadores en la regla, o si desea establecer el mensaje para una condición de error específica en un validador dado.
Puede especificar este metacomando usando la constante de clase
Zend_Filter_Input::MESSAGES en lugar de la
cadena.
A continuación se muestra un ejemplo simple de cómo establecer el mensaje de error por defecto para un único validador.
$validators = array(
'month' => array(
'digits',
'messages' => 'A month must consist only of digits'
)
);
Si tiene múltiples validadores para los que desea establecer el mensaje de error, debería usar un array como valor del metacomando 'messages'.
Cada elemento de este array se aplica al validador en la misma posición de índice. Puede especificar un mensaje para el validador en la posición n usando el valor n como índice del array. Así, puede permitir que algunos validadores usen su mensaje por defecto, mientras establece el mensaje para un validador posterior en la cadena.
$validators = array(
'month' => array(
'digits',
new Zend_Validate_Between(1, 12),
'messages' => array(
// use default message for validator [0]
// set new message for validator [1]
1 => 'A month value must be between 1 and 12'
)
)
);
Si uno de sus validadores tiene múltiples mensajes de error, se identifican mediante una clave de mensaje. Hay diferentes claves en cada clase validadora, que sirven como identificadores de los mensajes de error que la respectiva clase validadora podría generar. Cada clase de validación define constantes para sus claves de mensaje. Puede usar estas claves en el metacomando 'messages' pasando un array asociativo en lugar de una cadena.
$validators = array(
'month' => array(
'digits', new Zend_Validate_Between(1, 12),
'messages' => array(
'A month must consist only of digits',
array(
Zend_Validate_Between::NOT_BETWEEN =>
'Month value %value% must be between ' .
'%min% and %max%',
Zend_Validate_Between::NOT_BETWEEN_STRICT =>
'Month value %value% must be strictly between ' .
'%min% and %max%'
)
)
)
);
Debería consultar la documentación de cada clase validadora para saber si tiene múltiples mensajes de error, las claves de estos mensajes, y los tokens que puede usar en las plantillas de mensaje.
Si tiene solo un validador en la regla de validación o todos los validadores usados tienen el mismo conjunto de mensajes, entonces pueden referenciarse sin construcción adicional de array:
$validators = array(
'month' => array(
new Zend_Validate_Between(1, 12),
'messages' => array(
Zend_Validate_Between::NOT_BETWEEN =>
'Month value %value% must be between ' .
'%min% and %max%',
Zend_Validate_Between::NOT_BETWEEN_STRICT =>
'Month value %value% must be strictly between ' .
'%min% and %max%'
)
)
);
El valor por defecto de los metacomandos 'allowEmpty', 'breakChainOnFailure' y
'presence' puede establecerse para todas las reglas usando el
argumento $options del constructor de
Zend_Filter_Input. Esto le permite establecer el valor por defecto
para todas las reglas, sin necesidad de establecer el metacomando para
cada regla.
// The default is set so all fields allow an empty string.
$options = array('allowEmpty' => true);
// You can override this in a rule definition,
// if a field should not accept an empty string.
$validators = array(
'month' => array(
'Digits',
'allowEmpty' => false
)
);
$input = new Zend_Filter_Input($filters, $validators, $data, $options);
Los metacomandos 'fields', 'messages' y 'default' no pueden establecerse usando esta técnica.
Por defecto, cuando declara un filtro o validador como una cadena,
Zend_Filter_Input busca las clases correspondientes bajo
los espacios de nombres Zend_Filter o Zend_Validate.
Por ejemplo, un filtro nombrado por la cadena 'digits' se encuentra en la clase
Zend_Filter_Digits.
Si escribe sus propias clases de filtro o validador, o usa filtros
o validadores proporcionados por un tercero, las clases pueden existir en
espacios de nombres diferentes a Zend_Filter o
Zend_Validate. Puede indicarle a
Zend_Filter_Input que busque en más espacios de nombres. Puede especificar
los espacios de nombres en las opciones del constructor:
$options = array('filterNamespace' => 'My_Namespace_Filter',
'validatorNamespace' => 'My_Namespace_Validate');
$input = new Zend_Filter_Input($filters, $validators, $data, $options);
Alternativamente, puede usar los métodos addValidatorPrefixPath($prefix,
$path) o addFilterPrefixPath($prefix, $path),
que reenvían directamente al cargador de plugins que usa
Zend_Filter_Input:
$input->addValidatorPrefixPath('Other_Namespace', 'Other/Namespace');
$input->addFilterPrefixPath('Foo_Namespace', 'Foo/Namespace');
// Now the search order for validators is:
// 1. My_Namespace_Validate
// 2. Other_Namespace
// 3. Zend_Validate
// The search order for filters is:
// 1. My_Namespace_Filter
// 2. Foo_Namespace
// 3. Zend_Filter
No puede eliminar Zend_Filter y
Zend_Validate como espacios de nombres, solo puede añadir espacios de nombres.
Los espacios de nombres definidos por el usuario se buscan primero, los espacios de nombres de Zend se buscan al final.
![]() |
Nota |
|---|---|
A partir de la versión 1.5 la función |
![]() |
Nota |
|---|---|
A partir de la versión 1.0.4, |
![[Note]](images/note.png)
![[Warning]](images/warning.png)