HomePHP Page 4 - Developing a Form Validation System with the Observer Pattern in PHP
Getting the whole picture: listing the full source code for the data checking classes - PHP
Want to gain a good grounding in how to apply the Observer pattern in PHP? Then you’re in the right place! Welcome to the second part of the series “The Observer Pattern in PHP.” Composed of three tutorials, this series teaches you the key concepts of the popular Observer design pattern, and shows you how to apply it in the context of real-world PHP applications.
Culled from my own experience, I know that it’s much better to have all the source code listed in one place. For this simple reason, below I’ve listed all the data validation classes that I’ve defined in the previous section, so you can have a clear idea of how all the pieces fit together. Here they are:
// define DataValidator class class DataValidator{ protected $method; protected $formObserver; public function __construct(FormObserver $formObserver){ $this->formObserver=$formObserver; $this->method=$_POST; } protected function notifyObserver($errorMessage){ $this->formObserver->addNotification($errorMessage); } } // define StringValidator class class StringValidator extends DataValidator{ public function __construct($formObserver){ parent::__construct($formObserver); } // validate strings public function validate($field,$errorMessage,$min=4,$max=32){ if(!isset($this->method[$field])||trim($this->method [$field])==''||strlen($this->method[$field])<$min||strlen($this- >method[$field])>$max){ $this->notifyObserver($errorMessage); } } } // define IntegerValidator class class IntegerValidator extends DataValidator{ public function __construct($formObserver){ parent::__construct($formObserver); } // validate integers public function validate($field,$errorMessage){ if(!isset($this->method[$field])||!is_numeric($this- >method[$field])||intval($this->method[$field])!=$this->method [$field]){ $this->notifyObserver($errorMessage); } } } // define NumberValidator class class NumberValidator extends DataValidator{ public function __construct($formObserver){ parent::__construct($formObserver); } // validate numbers public function validate($field,$errorMessage){ if(!isset($this->method[$field])||!is_numeric($this- >method[$field])){ $this->notifyObserver($errorMessage); } } } // define RangeValidator class class RangeValidator extends DataValidator{ public function __construct($formObserver){ parent::__construct($formObserver); } // validate ranges public function validate($field,$errorMessage,$min=1,$max=99){ if(!isset($this->method[$field])||$this->method[$field] <$min||$this->method[$field]>$max){ $this->notifyObserver($errorMessage); } } } // define AlphaValidator class class AlphaValidator extends DataValidator{ public function __construct($formObserver){ parent::__construct($formObserver); } // validate alphabetic field public function validate($field,$errorMessage){ if(!isset($this->method[$field])||!preg_match("/^[a-zA-Z] +$/",$this->method[$field])){ $this->notifyObserver($errorMessage); } } } // define AlphanumValidator class class AlphanumValidator extends DataValidator{ public function __construct($formObserver){ parent::__construct($formObserver); // validate alphanumeric data public function validate($field,$errorMessage){ if(!isset($this->method[$field])||!preg_match("/^[a-zA- Z0-9]+$/",$this->method[$field])){ $this->notifyObserver($errorMessage); } } } // define EmailValidator class class EmailValidator extends DataValidator{ public function __construct($formObserver){ parent::__construct($formObserver); } // validate email public function validate($field,$errorMessage){ if(!isset($this->method[$field])||!preg_match ("/.+@.+..+/",$this->method[$field])||!checkdnsrr(array_pop (explode("@",$this->method[$field])),"MX")){ $this->notifyObserver($errorMessage); } } } // define EmailValidatorWin class (Windows systems) class EmailValidatorWin extends DataValidator{ public function __construct($formObserver){ parent::__construct($formObserver); } public function validate($field,$errorMessage){ if(!isset($this->method[$field])||!preg_match ("/.+@.+..+/",$this->method[$field])||!$this->windnsrr(array_pop (explode("@",$this->method[$field])),"MX")){ $this->notifyObserver($errorMessage); } } // private method 'windnsrr()' for Windows systems private function windnsrr($hostName,$recType=''){ if(!empty($hostName)){ if($recType=='')$recType="MX"; exec("nslookup -type=$recType $hostName",$result); foreach($result as $line){ if(preg_match("/^$hostName/",$line)){ return true; } } return false; } return false; } }
Here you have it. Now that you have the entire set of data validation classes listed in one place, feel free to improve them, in accordance with your specific programming requirements. It’s truly educational, believe me.
To wrap up
In this second article, you learned how to build a data validation system which uses independent objects for checking the validity of a broad range of user-supplied input, and also is capable of sending information about errors to a core object when user data fails to pass the verification process. However, the application is still incomplete, since the “core object” that I mentioned before remains undefined.
But, there’s no reason to panic. In the last article, I’ll show you how to define an observer object at the application’s core level, in this way providing the program with a centralized mechanism for making programmatic decisions based upon the errors that occurred when validating user-provided data. I'll meet you in the last tutorial!