Form validation (class ?)

Small, short code snippets that other people may find useful. Do you have a good regex that you would like to share? Share it! Even better, the code can be commented on, and improved.

Moderator: General Moderators

timvw
DevNet Master
Posts: 4897
Joined: Mon Jan 19, 2004 11:11 pm
Location: Leuven, Belgium

Post by timvw »

Dan is a regular at pear.php.net ;)
In CVS or alpha tree you will find the Validation package with a lot of local versions too ;)

http://pear.php.net/packages.php?catpid ... e=Validate
User avatar
phpScott
DevNet Resident
Posts: 1206
Joined: Wed Oct 09, 2002 6:51 pm
Location: Keele, U.K.

Post by phpScott »

using your nifftly class and all is going well except the isTelephoneNumber()

I have tried 01234567890
as well as 0123 4567 890

with and with out the leading 0

what is the match that it is looking for?

Cheers
User avatar
Chris Corbyn
Breakbeat Nuttzer
Posts: 13098
Joined: Wed Mar 24, 2004 7:57 am
Location: Melbourne, Australia

Post by Chris Corbyn »

phpScott wrote:using your nifftly class and all is going well except the isTelephoneNumber()

I have tried 01234567890
as well as 0123 4567 890

with and with out the leading 0

what is the match that it is looking for?

Cheers

Code: Select all

function isTelephoneNumber($input) {
    
        if (preg_match('/^(?:\+)?[\d ]+$/', $input)) {
            
            preg_match_all('/ /', $input, $matches);
            $count = count($matches[0]);
            if ($count > 4) {
                return false;
            } elseif ((strlen($input) - $count) < 10 || (strlen($input) - $count) > 15) {
                return false;
            } else {
                return true;
            } //End if
        
        } //End if
        return false;
    
    } //End isTelephoneNumber
There's a bug there :oops: It was missing a + on the character class. Use the function above.

I think this may have been mentioned (and a fix posted) in another posts in this thread but I haven't gone through to check.
User avatar
phpScott
DevNet Resident
Posts: 1206
Joined: Wed Oct 09, 2002 6:51 pm
Location: Keele, U.K.

Post by phpScott »

I didn't see one but it was a quick look.
Thanks for that.

One of these days I'm going to have to get my head around iregular expressions and the like.
I know there is a good tut on this site.
User avatar
Chris Corbyn
Breakbeat Nuttzer
Posts: 13098
Joined: Wed Mar 24, 2004 7:57 am
Location: Melbourne, Australia

Post by Chris Corbyn »

Just playing around with email validation and here's a better (although less obvious) regex for email address validation, using (sensible) dot-atom notation for the local part.

Code: Select all

<?php

function isValidEmail($string)
{
	$dot_atom_re = '[-!#\$%&\'\*\+\/=\?\^_`{}\|~0-9A-Z]+(?:\.[-!#\$%&\'\*\+\/=\?\^_`{}\|~0-9A-Z]+)*';
	$implemented_domain_re = '[-0-9A-Z]+(?:\.[-0-9A-Z]+)*';
	$full_pattern = '/^'.$dot_atom_re.'(?:@'.$implemented_domain_re.')?$/iD';
	if (preg_match($full_pattern, $string)) return true;
	else return false;
}

//Addresses marked ** should be INVALID, all others are actually valid
$test_addresses = array(
	'foo@bar.com',
	'foobar', //local networks
	'foo@bar', //local networks
	'foo&bar@bar.com',
	'foo-bar@bar-com.com.xy.0uy.test',
	'g.x.v.y\'test\'@home.tld',
	'g£h@foo.com', // **
	'bracket[addres]foo@bar.com', // **
	'@foo.com', // **
	'testy testy@foo.com', // **
	'chris=corbyn@bar',
	'chris@corbyn=bar', // **
	'$$$$****^^%!{}@test.tld' //valid!!!!
);

foreach ($test_addresses as $test)
{
	if (isValidEmail($test)) echo $test.' = Valid<br />';
	else echo $test.' = Invalid<br />';
}

?>
Prints:

Code: Select all

foo@bar.com = Valid
foobar = Valid
foo@bar = Valid
foo&bar@bar.com = Valid
foo-bar@bar-com.com.xy.0uy.test = Valid
g.x.v.y'test'@home.tld = Valid
g£h@foo.com = Invalid
bracket[addres]foo@bar.com = Invalid
@foo.com = Invalid
testy testy@foo.com = Invalid
chris=corbyn@bar = Valid
chris@corbyn=bar = Invalid
$$$$****^^%!{}@test.tld = Valid
There are a lot of email addresses you'd look at and assume are invalid, but are in fact valid. This function can be used for preventing header injection too if the only place you're adding user-defined headers is as an amil address.
User avatar
Luke
The Ninja Space Mod
Posts: 6424
Joined: Fri Aug 05, 2005 1:53 pm
Location: Paradise, CA

Post by Luke »

I'm getting this error for isMMDDYYYY...
PHP wrote:Warning: preg_match() [function.preg-match]: Unknown modifier '(' in formValidator.php on line 155
It does this no matter what I send it... any idea why?
User avatar
Burrito
Spockulator
Posts: 4715
Joined: Wed Feb 04, 2004 8:15 pm
Location: Eden, Utah

Post by Burrito »

try using a different seperator or modifying the pattern to something like this:

Code: Select all

$pattern = '#^(\\d{2})'.$sep.'(\\d{2})'.$sep.'(\\d{4})$#';
User avatar
Christopher
Site Administrator
Posts: 13596
Joined: Wed Aug 25, 2004 7:54 pm
Location: New York, NY, US

Post by Christopher »

I couldn't help myself from doing a pass over the code. :twisted: These should be split into separate files so you only use what you need. They also work with a Validator class.

Code: Select all

<?php
/*

Validator classes for PHP written by d11wtq (regex lover)
updated by arborint (monolithic class hater)

Version: 0.2.0
Last Updated: 3 Oct 2006

*/


class Validator_Rule_Name {

	/*
	 isName(). This is somewhat tricky to validate for ALL nationalities
	 -- don't use if you're not sure.  There wasn't much point doing separate
	 -- methods for first and last name.
	 */
	function isValid($input) {
		if (preg_match('/^\w[a-z\-\']+$/i', $input)) {
			return true;
		}
		return false;
			
	}
}

class Validator_Rule_Int {

	function isValid($input) {
		if (preg_match('/^\d+$/', $input)) {
			return true;
		}
		return false;
	}
}

class Validator_Rule_Float {

	function isValid($input) {
		if (preg_match('/^\d+(\.\d+)?$/', $input)) {
			return true;
		}
		return false;
	}
}

class Validator_Rule_Alpha {

	function isValid($input) {
		if (preg_match('/^[a-z]+$/i', $input)) {
			return true;
		}
		return false;
	}
}

class Validator_Rule_Lowercase {

	function isValid($input) {
		if (!preg_match('/[A-Z]/', $input) && preg_match('/[a-z]/', $input)) {
			return true;
		}
		return false;
	}
}

class Validator_Rule_Uppercase {

	function isValid($input) {
		if (preg_match('/[A-Z]/', $input) && !preg_match('/[a-z]/', $input)) {
			return true;
		}
		return false;
	}
}

class Validator_Rule_Creditcard {

	function isValid($input) {
		if (preg_match('/^\d{4}(?: )*\d{4}(?: )*\d{4}(?: )*\d{4}$/', $input)) {
			return true;
		}
		return false;
	}
}

class Validator_Rule_Telephone {

	/*
	 isTelephoneNumber(). No idea how this holds internationally I'm afraid
	 */
	function isValid($input) {
		if (preg_match('/^(?:\+)?[\d ]$/', $input)) {
			preg_match_all('/ /', $input, $matches);
			$count = count($matches[0]);
			if ($count > 4) {
				return false;
			} elseif ((strlen($input) - $count) < 10 || (strlen($input) - $count) > 15) {
				return false;
			} else {
				return true;
			}
		}
		return false;
	}
}

class Validator_Rule_Date {

	var $months_with_30_days = array (
          '04',
          '06',
          '09',
          '11'
          );
           
          var $months_with_31_days = array (
         '01',
         '03',
         '05',
         '07',
         '08',
         '10',
         '12'
         );

         var $months_with_28_days = '02';

         var $months = array (
        'JAN' => '01',
        'FEB' => '02',
        'MAR' => '03',
        'APR' => '04',
        'MAY' => '05',
        'JUN' => '06',
        'JUL' => '07',
        'AUG' => '08',
        'SEP' => '09',
        'OCT' => '10',
        'NOV' => '11',
        'DEC' => '12'
        );

        function daysValid($days) {
        	if (in_array($month, self::months_with_30_days)) {
        		if ($day > 30 || $day < 1) {
        			return false;
        		}
        		return true;
        	} elseif (in_array($month, self::months_with_31_days)) {
        		if ($day > 31 || $day < 1) {
        			return false;
        		}
        		return true;
        	} elseif ($month == self::months_with_28_days) {
        		if ($day > 29 || $day < 1) {
        			return false;
        		}
        		return true;
        	} else {
        		return false;
        	}
        }
}

class Validator_Rule_Date_DDMMYYYY extends Validator_Rule_Date {

	function isValid($input, $sep='/') {
		$pattern = '/^(\\d{2})'.$sep.'(\\d{2})'.$sep.'(\\d{4})$/';
		if (!preg_match($pattern, $input, $matches)) {
			return false;
		} else {
			return self::daysValid($matches[2], $matches[1]);
		}
			
	}
}

class Validator_Rule_Date_MMDDYYYY extends Validator_Rule_Date {

	function isValid($input, $sep='/') {
		$pattern = '/^(\\d{2})'.$sep.'(\\d{2})'.$sep.'(\\d{4})$/';
		if (!preg_match($pattern, $input, $matches)) {
			return false;
		} else {
			return self::daysValid($matches[1], $matches[2]);
		}
			
	}
}

class Validator_Rule_Date_DDMMYY extends Validator_Rule_Date {

	function isValid($input, $sep='/') {
		$pattern = '/^(\\d{2})'.$sep.'(\\d{2})'.$sep.'(\\d{2})$/';
		if (!preg_match($pattern, $input, $matches)) {
			return false;
		} else {
			return self::daysValid($matches[2], $matches[1]);
		}
	}
}

class Validator_Rule_Date_MMDDYY extends Validator_Rule_Date {

	function isValid($input, $sep='/') {
		$pattern = '/^(\\d{2})'.$sep.'(\\d{2})'.$sep.'(\\d{2})$/';
		if (!preg_match($pattern, $input, $matches)) {
			return false;
		} else {
			return self::daysValid($matches[1], $matches[2]);
		}
			
	}
}

class Validator_Rule_Date_DMYYYY extends Validator_Rule_Date {

	function isValid($input, $sep='/') {
		$pattern = '/^(\\d{1,2})'.$sep.'(\\d{1,2})'.$sep.'(\\d{4})$/';
		if (!preg_match($pattern, $input, $matches)) {
			return false;
		} else {
			if (strlen($matches[1] < 2)) {
				$matches[1] = '0'.$matches[1];
			}
			if (strlen($matches[2] < 2)) {
				$matches[2] = '0'.$matches[2];
			}
			return self::daysValid($matches[2], $matches[1]);
		}
			
	}
}

class Validator_Rule_Date_MDYYYY extends Validator_Rule_Date {

	function isValid($input, $sep='/') {
		$pattern = '^/(\\d{1,2})'.$sep.'(\\d{1,2})'.$sep.'(\\d{4})$/';
		if (!preg_match($pattern, $input, $matches)) {
			return false;
		} else {
			if (strlen($matches[1] < 2)) {
				$matches[1] = '0'.$matches[1];
			}
			if (strlen($matches[2] < 2)) {
				$matches[2] = '0'.$matches[2];
			}
			return self::daysValid($matches[1], $matches[2]);
		}
	}
}

class Validator_Rule_Date_DDMMMYYYY extends Validator_Rule_Date {

	function isValid($input, $sep='/') {
		$pattern = '/^(\\d{1,2})'.$sep.'(JAN|FEB|MAR|APR|MAY|JUN|JUL|AUG|SEP|OCT|NOV|DEC)'.$sep.'(\\d{4})$/i';
		if (!preg_match($pattern, $input, $matches)) {
			return false;
		} else {
			$months = self::months;
			if (!in_array($matches[2], $months)) {
				return false;
			}
			$matches[2] = $months[$m];
			return self::daysValid($matches[2], $matches[1]);
		}
	}
}

class Validator_Rule_Date_MMMDDYYYY extends Validator_Rule_Date {

	function isValid($input, $sep='/') {
		$pattern = '/^(JAN|FEB|MAR|APR|MAY|JUN|JUL|AUG|SEP|OCT|NOV|DEC)'.$sep.'(\\d{1,2})'.$sep.'(\\d{4})$/i';
		if (!preg_match($pattern, $input, $matches)) {
			return false;
		} else {
			$months = self::months;
			if (!in_array($matches[1], $months)) {
				return false;
			}
			$matches[1] = $months[$matches[1]];
			return self::daysValid($matches[1], $matches[2]);
		}
	}
}

class Validator_Rule_Ukpostcode {

	function isValid($input) {
		if (preg_match('/^[a-z]{1,2}\d{1,2}(?: )*[a-z]\d{1,2}$/i', $input)) {
			return true;
		}
		return false;
	}
}

class Validator_Rule_Uszipcode {

	function isValid($input) {
		if (preg_match('/^\d{5}([\- ]\d{4})?$/', $input)) {
			return true;
		}
		return false;
	}
}

class Validator_Rule_Email {

	function isValid($input) {
		if (preg_match('/^[a-z0-9]+[\w\-_\.]*?[a-z0-9]@[a-z0-9]+[a-z0-9\-\.]*\.[a-z]{2,}$/i', $input)) {
			return true;
		}
		return false;
	}
}

class Validator_Rule_Emailwithcommontld {

	/*
	 isEmailWithCommonTLD(). There's lots of TLD's... if what you need isn't validating,
	 -- simply add it to the final (?: ) list in the regex
	 */

	function isValid($input) {
		if (preg_match('/^[a-z0-9]+[\w\-_\.]*?[a-z0-9]@[a-z0-9]+[a-z0-9\-\.]*\.(?:com|uk|us|info|biz|gov|net|org|edu|ac|au|ca|de|eu|it|ro|ru|th)$/i', $input)) {
			return true;
		}
		return false;
	}
}

class Validator_Rule_Url {

	function isValid($input) {
		if (preg_match('@^https?://[a-z0-9]+[a-z0-9\-\.]*?\.[a-z]{2,}($|(/[^/]*/?$)|(\?.*$)|(#.*$))@i', $input)) {
			return true;
		}
		return false;
	}
}

class Validator_Rule_Url_Protocol {

	function isValid($input) {
		if (preg_match('#^[a-z]+\://#i', $input)) {
			return true;
		}
		return false;
	}
}

class Validator_Rule_Ipaddress {

	function isValid($input) {
		if( preg_match('/\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/', $input)) {
			return true;
		}
		return false;
	}
}
* edited to fix errors in code
Last edited by Christopher on Tue Oct 16, 2007 9:27 pm, edited 2 times in total.
(#10850)
User avatar
n00b Saibot
DevNet Resident
Posts: 1452
Joined: Fri Dec 24, 2004 2:59 am
Location: Lucknow, UP, India
Contact:

Post by n00b Saibot »

good pirate craft :P
User avatar
Chris Corbyn
Breakbeat Nuttzer
Posts: 13098
Joined: Wed Mar 24, 2004 7:57 am
Location: Melbourne, Australia

Post by Chris Corbyn »

It's not my fondest of creations :oops: Don't you love it when yucky code you wrote in the past keeps coming back to haunt you?
User avatar
Luke
The Ninja Space Mod
Posts: 6424
Joined: Fri Aug 05, 2005 1:53 pm
Location: Paradise, CA

Post by Luke »

haha sorry man... :oops:

::let's thread die::
User avatar
Chris Corbyn
Breakbeat Nuttzer
Posts: 13098
Joined: Wed Mar 24, 2004 7:57 am
Location: Melbourne, Australia

Post by Chris Corbyn »

I'm kidding man ;)

arborint just made the original one heaps better. It's interesting, I wrote HttpRequest object with the ability to attach validators recently. Now I'm TDDing with my new JST tool (unit testing for JS) to create a client-side form validator/filter. I'd completely forgotten I'd even written this.

The way I've done things lately is like this:

Code: Select all

$request = new Request($_POST);
$request->setValidator(new DefaultValidator(
    array(
        'username' => 'string',
        'email' => array('string', PCRE::email)
    )
));
I have a class full of PCRE patterns defined as const so I can just call them like above rather than having actual unique methods for validation.
User avatar
Luke
The Ninja Space Mod
Posts: 6424
Joined: Fri Aug 05, 2005 1:53 pm
Location: Paradise, CA

Post by Luke »

that's cool... I like that. hey whatever happened to that httprequest class we were working on... I kinda forgot about it... :oops:
User avatar
Chris Corbyn
Breakbeat Nuttzer
Posts: 13098
Joined: Wed Mar 24, 2004 7:57 am
Location: Melbourne, Australia

Post by Chris Corbyn »

Didn't we finish it? I can't remember.
User avatar
Luke
The Ninja Space Mod
Posts: 6424
Joined: Fri Aug 05, 2005 1:53 pm
Location: Paradise, CA

Post by Luke »

I don't know... work got completely insane for about a month and I kind of lost track of a lot of the things I was doing on the side for a while.
Post Reply