I have a function for parsing data, that goes to the database, (it's more validation, the sanitization process is taken care of by the framework). Here's my handmade script, based on a jQuery library, forgot its name. The comments are in Spanish.
/**
* Procesar Información.
*
* Compara la información proporcionada con las reglas establecidas para su validación.
* @param array $fields Arreglo con los campos y sus reglas de validación.
* @param array $data Arreglo con la información a validar.
* @param bool $strict Si es definido como true, marcará como ilegales los campos no definidos en las reglas,
* de lo contrario los ignora y toma como base las reglas.
* @return array Arreglo con los campos separados en legales e ilegales, de acuerdo a las reglas proporcionadas.
* @usage
* $reglas = array(
* 'nombre_campo'=>array(
* 'fieldname'=>'nombre_campo',
* 'label'=> 'Etiqueta descriptiva',
* 'rules'=> array(
* 'required'=>true,
* 'regex'=> 'Expresión regular',
* 'custom01'=>'funcion01', # Valida mediante funciones personalizadas.
* 'custom02'=>'funcion02' # Deben devolver true o false.
* ),
* 'errors'=> array(), # Opcional, debe coincidir con las reglas.
* 'required'=>'Mensaje de error para la regla required.',
* #El resto de las reglas despliega un mensaje predeterminado de error.
* ), ...
* );
* $datos = array('nombre_campo'=>'Valor a validar',...);
* $procesar = parseData($reglas, $datos);
*/
private function parseData(array $fields, array $data, $strict = false)
{
// Campos válidos.
$legal_fields = array();
// Campos no válidos.
$ilegal_fields = array();
foreach ( $fields as $field=>$attr)
{ #START FIELDS_LOOP
$isValid = true;
$error_msg='';
if(!empty($attr['rules']))
{#START RULES_PARSE
foreach($attr['rules'] as $rule=>$value)
{#START RULES_LOOP
// Si el valor no es válido, deja de comprobar el resto de las reglas.
// y marca el campo como ilegal con su correspondiente mensaje de error.
if(!$isValid)
{
break;
}
switch($rule)
{#START RULE_TYPE_SWITCH
// Para la regla requerido, se comprueba que la regla este definida como true y que el valor
// del campo no este vacío.
case 'required' :
$isValid = (!$value OR ($value=== true AND !empty($data[$attr['fieldname']])));
$error_msg = !empty($attr['errors'][$rule]) ? $attr['errors'][$rule]
: 'El campo '.$attr['label'].' es requerido.';
break;
case 'regex':
// Se compara el valor contra la expresión regular definida.
$isValid = (empty($value) OR
empty($data[$attr['fieldname']]) OR
(!empty($data[$attr['fieldname']]) AND preg_match($value, $data[$attr['fieldname']])));
$error_msg = !empty($attr['errors'][$rule]) ? $attr['errors'][$rule]
: 'El campo '.$attr['label'].' no tiene un formato válido.';
break;
case 'list':
$isValid = in_array($data[$attr['fieldname']], $value);
$error_msg = !empty($attr['errors'][$rule]) ? $attr['errors'][$rule]
: 'El campo '.$attr['label'].' no tiene un valor válido.';
break;
default:
// Para cualquier otro tipo de regla busca un método o función con el nombre definido
// y le pasa el valor del campo como argumento, la función debe devolver true o false
// únicamente despues de realizar la validación del valor.
if(!method_exists($this, $value) AND !function_exists($value))
{
throw new Exception('Method or function '.$value.' not found.');
}
$isValid = (empty($value) OR
empty($data[$attr['fieldname']]) OR
(
!empty($data[$attr['fieldname']]) AND
(
(method_exists($this, $value) AND $this->$value($data[$attr['fieldname']])) OR
(function_exists($value) AND $value($data[$attr['fieldname']]))
)
)
);
$error_msg = !empty($attr['errors'][$rule]) ? $attr['errors'][$rule]
: 'El campo '.$attr['label'].' no contiene un valor válido.';
break;
}#END RULE_TYPE_SWITCH
}#END RULES_LOOP
}#END RULES_PARSE
if($isValid)
{
$legal_fields[$attr['fieldname']] = !empty($data[$attr['fieldname']]) ?$data[$attr['fieldname']] : '' ;
}
else
{
$ilegal_fields[$attr['fieldname']]['value'] = !empty($data[$attr['fieldname']]) ?$data[$attr['fieldname']] : '' ;
$ilegal_fields[$attr['fieldname']]['error_msg'] = $error_msg;
}
}#END FIELDS_LOOP
if($strict)
{#START STRICT_MODE
foreach($data as $fieldname=>$value)
{
if(!isset($fields[$fieldname]))
{
$ilegal_fields[$fieldname]['value'] = $value;
$ilegal_fields[$fieldname]['error_msg'] = 'Campo '.$fieldname.' no reconocido.';
}
}
}#END STRICT_MODE
return array('legal' =>$legal_fields, 'ilegal'=>$ilegal_fields);
}#END parseData()
The usage it's very simple.
$parsedData = parseData($rules, $data);
Where the $data
is a simple array with the data in the form $fieldname => $value
and the $rules
are an array with the fields description to validate. Example
$fields = array(
'name'=> array(
'fieldname'=>'name',
'label' =>'Nombre',
'rules' => array(
'required' => true,
'regex'=>'/^\p{L}[\p{L} \']+$/u',
),
'errors'=> array(
'required' => 'Por favor proporcione su nombre.',
'regex'=>'El nombre debe contener únicamente letras, acentos y espacios.',
),
),
'apellidos'=> array(
'fieldname'=>'apellidos',
'label' =>'Apellidos',
'rules' => array(
'required' => true,
'regex'=>'/^\p{L}[\p{L} \']+$/u',
),
'errors'=> array(
'required' => 'Por favor proporcione sus apellidos.',
'regex'=>'Los apellidos solamente pueden contener letras, acentos y espacios.',
),
),
'description'=> array(
'fieldname'=>'description',
'label' =>'Descripción',
),
'fechadenacimiento'=> array(
'fieldname'=>'fechadenacimiento',
'label' =>'Fecha de Nacimiento',
'rules' => array(
'required' => false,
'regex' =>'/^[0-9]{4}-(0[1-9]|1[0-2])-(0[1-9]|[1-2][0-9]|3[0-1])$/',
'valid'=>'isValidDate',
),
'errors'=> array(
'required' => 'Por favor proporcione su fecha de nacimiento.',
'regex'=>'La fecha debe ser en el formato aaaa-mm-dd.',
'valid'=>'Por favor proporcione una fecha válida.',
),
),
The return is an array containing the legal (valid) and illegal (invalid) pair field values, the strict mode also verifies if the user add random unnecessary inputs on the contrary just ignore those. Any suggestions to improve it are welcome.