Validazione dell'input
Per la validazione dell'input, ho implementato una serie di classi figlie della classe AbstractValidator, forzando in questo modo la concreta implementazione dei metodi (dichiarati abstract) isValid e setError sfruttando poi il polimorfismo nella classe Validator.
Nb.Per ogni tipo di validazione ho preferito utilizzare una apposita funzione (nella libreria) piuttosto che mettere il relativo pattern della espressione regolare direttamente nella classe.In questo modo, a mio avviso, si ottiene una maggiore flessibilità della stessa.
Codice php:
/* imposta la direttiva error_reporting a runtime
E_ALL tutti gli errori compresi i notice
E_STRICT questa casistica di messaggi servono
ad aiutare le più recenti, e consigliate, metodologie
di programamzione, avvisando, ad esempio,
sull'uso di funzioni deprecate */
error_reporting(E_ALL | E_STRICT);
/* Definiamo una costante per ogni classe */
define('IS_VALID_STRING','Il campo %s contiene caratteri non ammessi o
non è
della lunghezza richiesta.');
/* la funzione con la regex */
function isValidString($str){
return (bool)preg_match('/^[A-Za-z0-9]{5,15}$/',$str);
}
class Validator{
/* Contiene le istanze delle
classi figlie di AbstractValidator */
private $validators= array();
/* Contiene i messaggi di errore delle classi figlie */
private $errors= array();
public function __construct(){}
/* Aggiunge una istanza di una classe figlia
di AbstractValidator */
public function add(AbstractValidator $validator){
$this->validators[]= $validator;
}
public function getErrors(){
return $this->errors;
}
/* Esegue una iterazione sull'array di oggetti
invocando per ciascuno il metodo isValid se il metodo
restituisce false (non è un valido input) assegna
a $isValid false e aggiunge il messaggio
di errore nell'array dedicato */
public function isValid(){
$isValid= true;
foreach($this->validators as $validator){
if(!$validator->isValid()){
$isValid= false;
$this->errors[] = $validator->getError();
}
}
return $isValid;
}
public function getFirstError(){
return $this->errors[0];
}
}
abstract class AbstractValidator{
protected $error= '';
abstract protected function isValid();
abstract protected function setError($msg);
public function getError(){
return $this->error;
}
}//
class IsValidString extends AbstractValidator{
private $value= '';
private $field= '';
public function __construct($field,$value){
$this->field= $field;
$this->value= $value;
}
public function isValid(){
$isValid= true;
/* Se l'input non è valido assegna
a $isValid false e setta il relativo errore*/
if(!isValidString($this->value)){
$isValid= false;
$this->setError(sprintf(IS_VALID_STRING,
$this->field));
}
return $isValid;
}
public function setError($msg){
$this->error= $msg;
}
}//
/* Esempio */
$validator= new Validator();
$validator->add(new IsValidString('username',"w_hisher"));
if($validator->isValid()){
//inserisci i datai nel DB
}
else{
foreach($validator->getErrors() as $msg){
echo $msg;
}
}
Captcha
La classe Image(parent), setta le dimensioni dell'immagine captcha, mentre la classe ImageGenerator(child), si serve della libreria di funzioni gd per la sua creazione.
La stringa casuale, è generata dalla classe RandomGenerator, cambiando il seme della proprietà privata chars, si può complicare ancora di più la vita, allo spambot di turno.
Rimando il lettore, a captcha decoder per conoscere più da vicino, le tecniche di decodifica delle immagini captcha.
Mailer
Per la spedizione delle varie email all'utente, utilizziamo l'insieme di classi Simple and Attachment Send Mail, dell'amico Gustavo Gomes, a cui vanno i credits.
Exception
Per la gestione degli errori a run-time, usiamo le exceptions, estendendo la classe Exception per ogni genere di errore possibile nello script in questo modo:
Codice php:
class InvalidArgException extends Exception{
public function __construct($message, $code = 0){
parent::__construct($message, $code);
}
public function __toString(){
return " ".__CLASS__ . "Line : [{$this->line}] Code :[{$this->code}] Msg : {$this->message} File : {$this->file}";
}
}
questo ci permette una gestione centralizzata e a cascata degli errori per chi volesse approfondire Error Handling I e Error Handling II.
Libreria
La libreria contiene un'insieme di funzioni, per gestire i compiti ripetivi del codice, l'unica che merita una qualche spiegazione è la seguente:
Codice php:
function getPostValue($key){
return isset($_POST[$key]) ? trim($_POST[$key]) : null;
}
function formHasVar(){
$hasVar= true;
/* recuperare i valori
passati alla funzione */
$args= func_get_args();
/* esegue una iterazione sull'array
$args, utilizza la funzione getPostValue
per scoprire se la chiave dell'array $_POST
è settata, se non lo fosse assegna a $hasVar false
*/
foreach($args as $arg){
if(is_null($value=getPostValue($arg))){
$hasVar= false;
}
}
/* se il numero dei valori passati
è diverso da quello dell'array $_POST
assegna a $hasVar false
*/
if(count($args)!==count($_POST)){
$hasVar= false;
}
return $hasVar;
}
//Esempio:
var_dump(formHasVar('username','send'));
è utilizzata per sapere se è stato fatto o meno il submit di una data form.
Conclusioni
Nel prossimo articolo parlerò finalmente, della vera e propria implementazione del sistema per la gestione degli utenti, analizzando in detaglio l'insieme di classi per il layout dei vari moduli.