2010-07-15 10 views
6

im a PHP Prüfklasse mit Unterklassen machen die sie erweitern, zum Beispiel Handy, vorort, CREDIT_CARD, ectphp Klassen ... Validierung

so ist die Idee kann man nennen

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

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

jetzt meine Idee, dies zu tun

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

als ein sehr einfaches Beispiel ist mit

aber gibt es einen besseren Weg, dies zu tun?

Antwort

9

Sie könnten es so machen, aber es könnte verbessert werden. Die eigene Validierungslogik zu haben ist gut. Erweitern sie von einer Basisklasse ist nicht. Lassen Sie uns stattdessen eine Schnittstelle implementieren. Auf diese Weise kann jede Klasse ein Validator sein.

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

Ihre Validatoren würde aussehen wie dieses dann:

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

und

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

Sie noch einen Haupt Validator-Klasse haben würde. Anders als in Ihrem Beispiel akzeptiert der folgende Validator mehrere Validatoren, mit denen Sie eine Filterkette erstellen können.

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

Und das könnte so verwendet werden:

die oben
$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 

ist so ziemlich ein Command pattern. Und da der Validator auch IValidate implementiert, ist es auch ein Composite. Sie könnten die Validator-Kette von oben nehmen und sie in eine andere Validator-Kette, z.B.

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

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

Der Einfachheit halber können Sie eine statische Factory-Methode für die Erstellung von Validatoren den tatsächlichen Validation Befehlsobjekte hinzufügen (wie an anderer Stelle gezeigt).

Auf einer Nebennote: the Zend Framework already has an extensive number of Validators you can build on. Da es sich bei ZF um eine Komponentenbibliothek handelt, können Sie diese verwenden, ohne Ihre gesamte Anwendung auf ZF migrieren zu müssen.

2

Normalerweise tun Sie diese Art von Dingen, die Fabrik Muster verwenden, etwa so:

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

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

wäre natürlich müssen einige Fehlerprüfung und solche, aber Sie sollten die Idee

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

erhalten Hinweis: Dieser Befehl gibt jedes Mal eine neue Instanz Ihrer Validator-Klasse zurück, so dass es besser wäre, das Factory-Muster zu verwenden, da Dennis den neuen Validator an die Methode type() gebunden hat oder nicht.