I have multiple form validation checks around my site so I decided to write them as functions to simplify the process of creating the validation pages, here is a snippet for an understanding of what I'm doing.
// Declare regex variables
$regex_email = "/^[a-zA-Z0-9._-]+@[a-zA-Z0-9-]+\.[a-zA-Z.]{2,5}$/";
$regex_password = "/^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*\W).*$/";
// Declare validation functions
function checkEmail($regex, $email) {
if (!preg_match($regex, $email)) {
$error = "The format of that Email Address is invalid";
$solution = "Please go back and <a href=\"javascript:history.go(-1)\">try again</a>";
}
return array($error, $solution);
}
function checkPassword($regex, $password) {
if (!preg_match($regex, $password)) {
$error = "Your Passwords does not meet our requirements";
$solution = "Please go back and <a href=\"javascript:history.go(-1)\">try again</a>";
}
return array($error, $solution);
}
I was hoping that when I come to validate it I could simply use:
// Values for $email and $password are fetched from `$_POST` before hand...
// Validate form
list ($error, $solution) = checkEmail($regex_email, $email);
list ($error, $solution) = checkPassword($regex_password, $password);
// Display error
echo("Error:<br />".$error."<br />Solution:<br />".$solution."");
But alas, it doesn't work and no errors at all are displayed and I'm having to do error checks after each one like this:
// Validate form
list ($error, $solution) = checkEmail($regex_email, $email);
if (!$error) {
list ($error, $solution) = checkPassword($regex_password, $password);
}
// Display error
echo("Error:<br />".$error."<br />Solution:<br />".$solution."");
I don't mind doing it like this, but when I have say 10+ check*VALUE*
functions being called, each one wrapped in an if statement
within an if statement
and so on, it looks a little messy, I wasn't sure if there was a different approach which would work more like the first way I tried without all the if statement
's.
-
\$\begingroup\$ Javascript in your backlinks. Just give them a class and hook the javascript into that class, so that if you ever want to change the behavior, you can change it in the js instead of everywhere in the php code. \$\endgroup\$Kzqai– Kzqai2011年11月13日 18:32:56 +00:00Commented Nov 13, 2011 at 18:32
2 Answers 2
I'd do the following:
function checkEmail($errors, $email) {
$regex_email = "/^[a-zA-Z0-9._-]+@[a-zA-Z0-9-]+\.[a-zA-Z.]{2,5}$/";
if (!preg_match($regex_email, $email)) {
array_push($errors, "The format of that Email Address is invalid");
array_push($solutions, "Please go back and <a ...>try again</a>");
}
return array($errors, $solution);
}
$errors = array();
$solutions = array();
list ($errors, $solutions) = checkEmail($errors, $solutions, $email);
// ...
if (count($errors) > 0) {
// TODO: print the errors
}
Consider declaring the $regex_mail
variable inside the checkEmail
function.
-
\$\begingroup\$ I'm not at my computer with all my files to test this out, but from reading it, would that list ALL the errors or just the first one it detects? I was hoping to just display the first error it says, rather than a big list, but I'm sure I can figure that out with something. Thanks for the heads up on the position of the regex variables declarations too! If I get it working I'll be back to mark it as top answer. \$\endgroup\$no.– no.2011年11月07日 10:52:16 +00:00Commented Nov 7, 2011 at 10:52
This might not be what you are looking for but I recently wrote this code to validate my forms.
As you might notice I define the data to be validated in the $validate array. Then some loops run through them and show the proper errors. If no errors are found, it sends the form.
With some modifications, you could probably use something similar. Hope it helps.
<?php
# post data collection
$name = "Full name";
$email = "[email protected]";
$age = "193";
$x = "s";
$y = "s";
# select data that needs validation
$validate = array(
'required' => array($name, $email, $x, $y),
'validEmail' => array($email),
'validNumber' => array($age),
'validAlpha' => array($name)
);
# error messages
$errorsMsgs = array(
'required' => 'Please fill out all required fields.',
'validEmail' => 'is an invalid email address.',
'validNumber' => 'is an invalid number.',
'validAlpha' => 'contains invalid characters. This field only accepts letters and spaces.'
);
$errorMarkup = "<h1>We found a few errors :-(</h1><h2>Please fix these errors and try again</h2><ol>";
$successMarkup = "<h1>Success!</h1><h2>Your form was sent successfully.</h2>";
$backMarkup = "<a href=\"" . $_SERVER['HTTP_REFERER'] . "\">Back to form</a>";
# begin state
$valid = true;
# loop through fields of error types
foreach ($validate as $type => $fields) {
# loop through values of fields to be tested
foreach ($fields as $value) {
# throw error if value is required and not entered
if ($type === 'required' && strlen($value) === 0) {
$errorMarkup .= "<li>$errorsMsgs[$type]</li>";
$valid = false;
break;
}
else if (
$type === 'validEmail' && !filter_var($value, FILTER_VALIDATE_EMAIL) ||
$type === 'validNumber' && !preg_match('/^[0-9 ]+$/', $value) ||
$type === 'validAlpha' && !preg_match('/^[a-zA-Z ]+$/', $value)
) {
if (strlen($value) === 0) {break;} # skip check if value is not entered
$errorMarkup .= "<li>\"$value\" $errorsMsgs[$type]</li>";
$valid = false;
continue;
}
}
}
if ($valid) {
# email form
$body = $successMarkup . $backMarkup;
$title = "Form sent";
} else {
$body = $errorMarkup . "</ol>" . $backMarkup;
$title = "Form errors";
}
# write html ouput
echo "<!DOCTYPE html><head><title>$title</title><style type=\"text/css\">body{margin:100px;font:16px/1.5 sans-serif;color:#111}h1{font-size:32px;margin:0;font-weight:bold}h2{font-size:18px;margin:0 0 20px 0}ol,li{list-style-position:inside;padding-left:0;margin-left:0}</style></head><body>$body</body></html>";
?>
-
1\$\begingroup\$ Thank you for the example kht! I was hoping to stick to the approach I've taken since it works well with everything I've got so far. But it's good to have a working alternative! +1 \$\endgroup\$no.– no.2011年11月06日 17:12:14 +00:00Commented Nov 6, 2011 at 17:12