Multiple conditions in one statement - php

I'm adding some very basic validation to a "name" form field. Generally, it's impossible to actually validate a name, but I figured I could at least verify that it's not empty, greater than maybe 2 characters (Al is the shortest name I can think of), and that those characters aren't just empty space.
Here's the conditionals I'm using:
// Check length of name field
if(!isset($name) || $name < 2 || (strlen($name) > 0 && strlen(trim($name)) == 0)) {
// Name field only spaces
if((strlen($name) > 0 && strlen(trim($name)) == 0) || trim($name) == '') {
$errors['name'] = "Please enter a real name...";
}
// Name too short
else {
$errors['name'] = "Are you sure <strong>".htmlspecialchars($name)."</strong> is your name?";
}
$msg_type = "error";
}
However, when I run this with a valid name, I get the "Name too short" error. I know it's got to be a problem with how I'm combining the conditionals, but I can't figure out where that problem lies.

$name < 2 doesn't work. You're trying to use strlen($name) < 2.

Well, there is a tool called regex which people have invented for string matching and it could be pretty conveniently used for validation cases like yours. If you want to validate a word let's say with at least 2 characters of length, you could do the following:
if(!preg_match('/\b\w{2,}/', $name)) {
$errors['name'] = "Are you sure <strong>".htmlspecialchars($name)."</strong> is your name?";
}
Where:
\b: word boundary
\w: word character
{2,}: two or more times for the word character

Related

Function for normalizing Canadian postal codes is returning unexpected results

I'm trying to normalize user input for Canadian postal codes.
The end goal is to get all input as A3A 3A3 - 7 characters, capitalized, with the first group letter number letter, second group as number letter number.
Users will sometimes use o or O for the number 0, or vice versa, so here is my function:
$zip = htmlspecialchars($_REQUEST['zip']);
if (!empty($zip)) {
//if the format is A3A3A3, split it into two groups
if (strlen($zip) == 6) {
$zip = substr($zip, 0, 3) . " " . substr($zip, 3, 3);
}
//now lets make sure there is only a empty space between groups
if (strlen($zip) == 7) {
$zip[3] = " ";
}
//let's put their o's, O's and 0's in the right places
if ($zip[1] == ("O" || "o")) {
$zip[1] = '0';
}
if ($zip[4] == ('O'||'o')) {
$zip[4] = '0';
}
if ($zip[6] == ('O'||'o')) {
$zip[6] = '0';
}
if ($zip[0] == '0') {
$zip[0] = 'O';
}
if ($zip[2] == '0') {
$zip[2] = 'O';
}
if ($zip[5] == '0') {
$zip[5] = 'O';
}
//uppercase all the letters
strtoupper($zip);
}
The first tests I ran were of the sort:
input[0o0 O0o] => output[O0O 0O0]
Everything looks good I said to myself, it's working! But then I tried a normal postal code and keep getting unexpected results:
input[S7K3K1] => output[S0K 0K0]
I can't figure out why the code is deciding that ($zip[1] == ('O' || 'o') is true when $zip[1] == 7.
Any input would be greatly appreciated. Also, if you see a better way of normalizing this input, please share!
//let's put their o's, O's and 0's in the right places
if ($zip[1] == ("O" || "o")) {
$zip[1] = '0';
}
This code does not do what you think – your comparison logic are wrong, because so is your understanding of the || operator.
Use console.log(("O" || "o")) and see what you get in console – ooops, that’s just the letter O. Why? Because the || logical or operator in JS returns the first value that is not false-y.
You need to either write two individual comparisons here, and or-conjoin those – $zip[1] == "O" || $zip[1] == "o", or use an array with possible values and then check whether your variable value is among those (but the latter would be a bit over the top here).
Edit: Or, as bigmandan pointed out, you could also transform your letter to upper- or lower-case first, then you only have to do one comparison: ($zip[1]).toLowerCase() == "o" (Of course this works only in a special case like this – if it was not O or o, but a or b instead, you would still have to do individual comparisons.)

preg_match admits only two consecutive lowercases

I want to check if password contains:
minimum 2 lower cases
minimum 1 upper case
minimum 2 selected special characters
The problem is that when i want to verify this,it admits two lowercases,but only if they are consecutive,like this:paSWORD .
if I enter pASWORd,it returns an error.
This is the code
preg_match("/^(?=.*[a-z]{2})(?=.*[A-Z])(?=.*[_|!|#|#|$|%|^|&|*]{2}).+$/")
I don't see where the problem is and how to fix it.
You're looking for [a-z]{2} in your regex. That is two consecutive lowercases!
I will go out on a limb and suggest that it is probably better to individually check each of your three conditions in separate regexes rather than trying to be clever and do it in one.
I've put some extra braces in which may get your original idea to work for non-consecutive lowercase/special chars, but I think the expression is overcomplex.
preg_match("/^(?=(.*[a-z]){2})(?=.*[A-Z])(?=(.*[_!##$%^&*]){2}).+$/")
You can use this pattern to check the three rules:
preg_match("/(?=.*[a-z].*[a-z])(?=.*[A-Z])(?=.*[_!##$%^&*].*[_!##$%^&*])/");
but if you want to allow only letters and these special characters, you must add:
preg_match("/^(?=.*[a-z].*[a-z])(?=.*[A-Z])(?=.*[_!##$%^&*].*[_!##$%^&*])[a-zA-Z_!##%^&*]+$/");
a way without regex
$str = '*MauriceAimeLeJambon*';
$chars = 'abcdefghijklmnopqrtuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_!##$%^&*';
$state = array('lower' => 2, 'upper' => 1, 'special' => 2);
$strlength = strlen($str);
for ($i=0; $i<$strlength; $i++) {
$pos = strpos($chars, $str[$i]);
if (is_numeric($pos)) {
if ($state['lower'] && $pos<26) $state['lower']--;
elseif ($state['upper'] && $pos<52) $state['upper']--;
elseif ($state['special']) $state['special']--;
} else { $res = false; break; }
$res = !$state['lower'] && !$state['upper'] && !$state['special'];
}
var_dump($res);
(This version give the same result than the second pattern. If you want the same result than the first pattern, just remove the else {} and put the last line out of the for loop.)

Simple 'Greater Than' form validation

I am trying to validate my registration form, and one of my validations doesn't work. I want to echo a error message if the first name is over 20 characters long. I am using the code
} else if($_POST["mem_first_name"] >20) {
$errors[] = 'Sorry but your First name is limited to 20 Characters each';
}
However no error is shown if more than 20 characters are entered. However if I use the same code but change it to less than like this
} else if($_POST["mem_first_name"] <20) {
$errors[] = 'Sorry but your First name is limited to 20 Characters each';
}
Then it works, is there a simple fix?
if(strlen($_POST["mem_first_name"]) > 20)
Use strlen() function
} else if(strlen($_POST["mem_first_name"]) >20) {
$errors[] = 'Sorry but your First name is limited to 20 Characters each';
}
How about using the strlen() function, for counting strings? It is stable and appropriate way of counting number of characters IMO
} else if(strlen($_POST["mem_first_name"]) >20) {
$errors[] = 'Sorry but your First name is limited to 20 Characters each';
}
You have to use strlen() function for string length checks. Also, be aware that if you need multibyte encoding support, you should switch to using mb_strlen().
var_dump(strlen('bär')); // int(4) - byte length
var_dump(mb_strlen('bär', 'utf8')); // int(3) - character length

Numeric input validation in PHP

I'm trying to validate an input for Account number in php form. It should contain 8 numbers and '-' optionally. If there is '-' - it should be ignored.
After pressing the Submit button, the warning message suppose to be displayed above the form in case input is invalid.
Please help.
This is what I got so far, but I'm not sure if this is correct and don't know how to display a warning message above the form.
$acctnum= "$acctnum";
if(empty($acctnum)){
echo "You did not enter an account number, please re-enter"; }
else if(!preg_match("\-^[0-9]{8}", $acctnum)){
echo "Your account number can only contain eight numbers. Please re-enter."; }
Thank you!
You don't appear to be trying. No documentation or tutorial will tell you to make a Regex like that. For starters, where are the delimiters? Why is - escaped when it's outside a character class and therefore has no special meaning? What is that ^ doing there?
This should do it:
$acctnum = str_replace("-","",$acctnum);
if( !preg_match("/^\d{8}$/",$acctnum)) echo "Error...";
Since regex are quite expensive I'd go like that instead:
$acctnum = (int) $acctnum; // this automatically ignore the '-'
if ($acctnum < 0) $acctnum = -$acctnum;
$digits = ($acctnum == 0) ? log10($acctnum) + 1 : 1;
if ($digits === 8) { ... }
Split the task in two. First get rid of the "-" with str_replace and then check for the numbers.
$match = preg_match("/^\d{8}$/", str_replace("_", "", $str));
if ($match > 0) {
// Correct
} else {
// incorrect
}

Validate Phone Number and Zip Code PHP

I am trying to validate a phone number and require it to have 10 digits only no spaces or special characters allowed (example: 0123456789) and the same goes with zip code except 5 digits only (example: 01234).
This is what I have for the phone number field so far.
$phone = stripslashes($_POST['phone']);
if(!$phone || $phone == "Phone Number*")
{
$error .= "Please enter your phone number.<br />";
}
The next if statement should retrieve an error similar to "Please enter a valid phone number. Example: "0123456789".
If you don't want to use regular expressions, take a look at ctype_digit
For example:
if(strlen($phone)==10 && ctype_digit($phone)) {
//valid
} else {
//invalid
}
I can't testify to whether this will be faster or slower than regular expressions, but I would reckon it's probably moot. It's more or less what makes the most sense to you.
You can try regex here:
if(preg_match('/^[0-9]{10}$/', $phone)){
// valid
}else{
// Not valid
}
Something a little like that will ensure only numerical characters and 10 of them. Just change the 10 to 5 for zip code.
One more thing if $_POST['phone'] is not set when you access it you will get a E_NOTICE so just a tip here for you do:
$phone = isset($_POST['phone']) ? stripslashes($_POST['phone']) : null;
if(!$phone) // ERROR
$phone = stripslashes($_POST['phone']);
if(!$phone || $phone == "Phone Number*")
{
$error .= "Please enter your phone number.<br />";
}
if(!preg_match('/^\d{10}$/', $phone)) $error .= "Please enter phone number as ##########.<br />";
And for zip code
if(!preg_match('/^\d{5}$/', $zip)) $error .= "Please enter your zip code as #####.<br />";
Keep in mind that this will not allow foreign zip codes (which may be of different lengths or include letters)
Just some other suggestions too (to prevent unnecessary error messages)
You may want to process your user input such that 123-456-7890 becomes 1234567890 by doing something like
preg_replace('/[^\d]/','',$input)
Maybe do a trim($input) to strip leading/trailing whitespace
Finally, is there any particular reason you are using stripslashes on $_POST['phone']?
If they are all digits like you expect, then this shouldnt be necessary.
If they aren't all digits, then you will throw an error regardless
how about:
function check($number,$length)
{
if(ctype_digit ($number) && strlen($number)==$length)
return true;
else
return false;
}
if(check("1234",4))
echo "ok";
else
echo "Please enter a valid phone number. Example: "0123456789";
Well, this an old post but I will throw in some comments here anyway.
1) you should really not force the user to put in the right numbers, of course your validation on the front end will cover this but never assume it to be case coming into the "backend" .
Consider the following instead of putting the on the user:
// remove chars
$number = preg_replace('/[\D]/', '', $number);
//unit test sanitizer
filter_var($number, FILTER_SANITIZE_NUMBER_INT)
// check number
preg_match('/^[0-9]{10}$/', $zip)
Example : Read in user input if enough digits entered in look up closest matching zipcode etc.. (I actually used this on a site once) Of course setting the frontend to check is useful, but in case that fails .
$number = 'z 02012s';
// remove chars
$number = preg_replace('/[\D]/', '', $number);
//unit test sanitizer
$number = filter_var($number, FILTER_SANITIZE_NUMBER_INT);
// check number
if (preg_match('#^[0-9]{5}$#', $number) === 1) {
//(optional) lookup closest zip using your DB.
$look_zip = $db->getClosestZipMatch($number);
} else {
echo $number . " isn't 5 digits only, do something.";
}

Categories