2010-07-15 19 views
6

im estoy haciendo una clase de validación php con subclases que se extienden que, por ejemplo, móvil, suburbio, CREDIT_CARD, ectclases php ... validación

así, la idea es que se puede llamar

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

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

ahora mi idea de hacer esto es tener

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); 
    } 
} 

como un ejemplo muy básico

, pero ¿hay una mejor manera de hacerlo?

Respuesta

9

Podría hacerlo de esta manera, pero podría mejorarse. Tener los validadores reales en cápsula con su propia lógica de validación es bueno. Extenderlos desde una clase base no lo es. Implementemos una interfaz en su lugar. De esta forma, cualquier clase puede ser un Validador.

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

Sus validadores se vería así entonces:

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

y

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

usted todavía tienen una clase principal validador. A diferencia de su ejemplo, el Validador a continuación acepta múltiples Validadores, lo que le permitirá crear una Cadena de Filtro.

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; 
    } 
} 

Y esto podría ser utilizado como:

$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 

Lo anterior es más o menos un Command pattern. Y debido a que el Validator también implementa IValidate, también es un Composite. Puede tomar la cadena del Validator desde arriba y apilarla en otra Cadena del Validador, p.

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

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

Para mayor comodidad, se puede añadir un método de fábrica estática para crear validadores con los objetos reales Validación de comando (como se muestra en otros lugares).

En una nota al margen: the Zend Framework already has an extensive number of Validators you can build on. Dado que ZF es una biblioteca de componentes, puede usarlos sin tener que migrar toda su aplicación a ZF.

2

Por lo general lo hace este tipo de cosas utilizando el patrón de fábrica, algo como esto:

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

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

sería, por supuesto necesita un poco de comprobación de errores y tal, pero usted debe conseguir la idea

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

Nota: Esta vez, cada vez que se devuelve una nueva instancia de su clase de Validator, sería una mejor idea usar el patrón Factory como Dennis sugirió o no vincular el nuevo Validator con el método type().