Minimal input validator class

Coding Critique is the place to post source code for peer review by other members of DevNetwork. Any kind of code can be posted. Code posted does not have to be limited to PHP. All members are invited to contribute constructive criticism with the goal of improving the code. Posted code should include some background information about it and what areas you specifically would like help with.

Popular code excerpts may be moved to "Code Snippets" by the moderators.

Moderator: General Moderators

Post Reply
User avatar
lorenzo-s
Forum Commoner
Posts: 43
Joined: Tue Aug 25, 2009 12:25 pm

Minimal input validator class

Post by lorenzo-s »

Hi everyone. Yesterday I've coded a simple input validator class. The goal is to quickly check forms input values and store error messages for each one. That's it:

Code: Select all

    class Validator {
        
        // Error list
        private $errors = array();
        
        // Validating options
        const NOT_EMPTY = 1;
        const NUMERIC   = 2;
        const INTEGER   = 4;
        const UNSIGNED  = 8;
        const ALPHA_NUM = 16;
        const EMAIL     = 32;
        const REG_EXPR  = 64;
        
        /** Validate a valu ewith specified options and set error on fail
         * @param $key Identifier of the value
         * @param $value Value to check
         * @param $message Error message to set
         * @param $options Validating options
         * @param $reg_exp Optional regular expression, if Validator::REG_EXPR is int the options */
        public function check($key, $value, $message, $options = self::NOT_EMPTY, $reg_expr = null) {
            
            // Check for numeric value
            if ($options & self::NUMERIC) if (
                (!String::isNumeric($value)) ||
                (($options & self::NOT_EMPTY) && ($value == 0)) ||
                (($options & self::UNSIGNED ) && ($value <  0))
            ) {
                $this->errors[$key] = $message;
                return;
            }
            
            // Check for integer value
            if ($options & self::INTEGER) if (
                (!String::isInteger($value)) ||
                (($options & self::NOT_EMPTY) && ($value == 0)) ||
                (($options & self::UNSIGNED ) && ($value <  0))
            ) {
                $this->errors[$key] = $message;
                return;
            }
            
            // Check for alphanumeric strings
            if ($options & self::ALPHA_NUM) if (
                (!String::isAlphanum($value))
            ) {
                $this->errors[$key] = $message;
                return;
            }
            
            // Check for valid email
            if ($options & self::EMAIL); // TODO email check with preg_match()
            
            // Check with regular expression
            if ($options & self::REG_EXPR); // TODO check with preg_match() with $reg_expr
            
            // Check empty string, or null, or false value (not 0 or "0"!)
            if ($options & self::NOT_EMPTY) if (
                ($value === '') ||
                ($value === null) ||
                ($value === false)
            ) {
                $this->errors[$key] = $message;
                return;
            }
            
        }
        
        /** Returns TRUE if there are no errors */
        public function isOk() {
            return (empty($this->errors));
        }
        
        /** Get the error list as associative array */
        public function getErrors() {
            return $this->errors;
        }
        
        /** Reset the error list */
        public function reset() {
            $this->errors = array();
        }
        
    } 
I will use it in that way:

Code: Select all

    // Check POST
    $val = new Validator();
    $val->check('name', $_POST['name'], 'Insert your name here', Validator::NOT_EMPTY);
    $val->check('mail', $_POST['mail'], 'Type a correct email address', Validator::EMAIL | Validator::NOT_EMPTY);
    $val->check('age' , $_POST['age' ], 'Invalid age!', Validator::INTEGER | Validator::UNSIGNED);
    
    // Get errors
    if (!$val->isOk()) $errors = $val->getErrors();
    else {
        // Do stuff on correct values
    }
    
    // Before each HTML form fields
    if ($errors['name']) echo '<p class="error">' . htmlentities($errors['name']) . '</p>';
What do you think about it? Too much simple? Too much difficult to use?? :D
User avatar
Christopher
Site Administrator
Posts: 13596
Joined: Wed Aug 25, 2004 7:54 pm
Location: New York, NY, US

Re: Minimal input validator class

Post by Christopher »

Simpler might be:

Code: Select all

    // Check POST
    $val = new Validator($_POST);
    $val->checkEmpty('name', 'Insert your name here');
    $val->checkEmail('mail', 'Type a correct email address');
    $val->checkInteger('age' , 'Invalid age!');
I'd prefer it was not monolithic, but for a simple solution this looks good.
(#10850)
User avatar
lorenzo-s
Forum Commoner
Posts: 43
Joined: Tue Aug 25, 2009 12:25 pm

Re: Minimal input validator class

Post by lorenzo-s »

Pass the values array in the Validator constructor it's a good idea!
About the multiple function, yes, it's shorter and easier, but if I want to check that an integer is unsigned, non zero and satisfy a regular expression, I have to call four function instead of one...
User avatar
Christopher
Site Administrator
Posts: 13596
Joined: Wed Aug 25, 2004 7:54 pm
Location: New York, NY, US

Re: Minimal input validator class

Post by Christopher »

lorenzo-s wrote:About the multiple function, yes, it's shorter and easier, but if I want to check that an integer is unsigned, non zero and satisfy a regular expression, I have to call four function instead of one...
For more complex validation, I would recommend having a separate classes for each rule. Then you can pass several rule objects for a single field.
(#10850)
Post Reply