2010-07-15 14 views
6

im sto facendo una classe di convalida PHP con le sottoclassi che estendono essa, ad esempio, mobili, sobborgo, CREDIT_CARD, ectclassi PHP ... validazione

così, l'idea è che si può chiamare

$validation = new Validation('mobile'); 
$valid = $validation->validate($number); 

$validation->type('suburb'); 
$valid2 = $validation->validate($suburb); 

ora la mia idea per fare questo sta avendo

class Validation() { 
    private $v_type = null; 

    function __construct($type) { 
     $this->type($type); 
    } 

    public function type($type) { 
     $this->v_type = new $type(); 
    } 

    public function validate($info) { 
     return $this->v_type->validate($info); 
    } 
} 

come un esempio molto semplice

ma c'è un modo migliore per farlo?

risposta

9

Si potrebbe fare in questo modo, ma potrebbe essere migliorato. Avendo la capsula dei validatori effettivi la loro logica di validazione è buona. Estendendoli da una classe base non lo è. Implementiamo invece un'interfaccia. In questo modo, qualsiasi classe può essere un Validator.

interface IValidate 
{ 
    public function validate($value); 
} 

vostri validatori apparirebbe come questo allora:

class IsNumeric implements IValidate 
{ 
    public function validate($value) 
    { 
     return is_numeric($value); 
    } 
} 

e

class GreaterThan implements IValidate 
{ 
    protected $_value; 
    public function __construct($value) 
    { 
     $this->_value = $value; 
    } 
    public function validate($value) 
    { 
     return $value > $this->_value; 
    } 
} 

saresti ancora dispone di una classe Validator principale. A differenza del tuo esempio, il Validator in basso accetta più Validator, che ti permetteranno di creare una catena di filtri.

class Validator implements IValidate 
{ 
    protected $_validators; 

    public function addValidator(IValidate $validator) 
    { 
     $this->_validators[] = $validator; 
     return $this; 
    } 
    public function validate($value) 
    { 
     foreach($this->_validators as $validator) { 
      if ($validator->validate($value) === FALSE) { 
       return FALSE; 
      } 
     } 
     return TRUE; 
    } 
} 

E questo potrebbe essere usato come:

$validator = new Validator; 
$validator->addValidator(new IsNumeric) 
      ->addValidator(new GreaterThan(5)); 

var_dump($validator->validate('ten')); // FALSE 
var_dump($validator->validate('10')); // TRUE 
var_dump($validator->validate('1')); // FALSE 

Quanto sopra è praticamente una Command pattern. E a causa del Validator che implementa anche IValidate, è anche un Composite. Puoi prendere la catena Validator da sopra e impilarla in un'altra catena di Validator, ad es.

$numericGreaterThanFive = new Validator; 
$numericGreaterThanFive->addValidator(new IsNumeric) 
         ->addValidator(new GreaterThan(5)); 

$otherValidator = new Validator; 
$otherValidator->addValidator(new Foo) 
       ->addValidator(new Bar) 
       ->addValidator($numericGreatherThanFive); 

Per comodità, è possibile aggiungere un metodo factory statico per la creazione di validatori con gli oggetti di convalida comando effettivo (come mostrato altrove).

Su un sidenote: the Zend Framework already has an extensive number of Validators you can build on. Poiché ZF è una libreria di componenti, è possibile utilizzarli senza dover migrare l'intera applicazione a ZF.

2

Di solito si fa questo genere di cose che utilizzano il modello di fabbrica, qualcosa di simile:

class ValidatorFactory { 
    public static function get($type) { 
     $validator = "Validator_$type"; 
     return new $validator(); 
    } 
} 

$valid = ValidatorFactory::get('mobile')->validate($number); 

sarebbe ovviamente bisogno di qualche controllo degli errori e così, ma si dovrebbe ottenere l'idea

0
... 
public function type($type) { 
    return new self($type); 
} 
... 

Nota: questa volta ogni volta restituisce una nuova istanza della classe Validator, quindi sarebbe meglio usare il modello Factory come suggerito da Dennis per legare il nuovo Validator al metodo type().