I have am trying to re-create a form register validation that I seen a few weeks ago but unable to figure it out.
I want to perform one last check after the first 3 checks then display the message
validation code
public function validateSignup(): bool
{
$this->errors = [];
if (empty($this->name) || (strlen($this->name) < 4)) {
$this->errors['name'] = "Username must be at least 4 characters.";
}
if (empty($this->email) || (filter_var($this->email, FILTER_VALIDATE_EMAIL) === false)) {
$this->errors['email'] = "Email address is required.";
}
if (empty($this->password) || strlen($this->password) < 6) {
$this->errors['password'] = "Password is required.";
}
return empty($this->errors);
}
This works great for the validation requirements but I want to add another step, to check if email or username is taken, I know how to do this traditionally but wanted to make it different without giving information away.
I have a Helper to tell me if an email is in the database called alreadyExists
what I am trying to accomplish is a 2nd check after that
Example
public function validateSignup(): bool
{
$this->errors = [];
if (empty($this->name) || (strlen($this->name) < 4)) {
$this->errors['name'] = "Username must be at least 4 characters.";
}
if (empty($this->email) || (filter_var($this->email, FILTER_VALIDATE_EMAIL) === false)) {
$this->errors['email'] = "Email address is required.";
}
if (empty($this->password) || strlen($this->password) < 6) {
$this->errors['password'] = "Password is required.";
}
return empty($this->errors);
## after it checks validation with no errors check if already exists
if ($this->name) Helpers::alreadyExists("user", "name", $this->name) {
$this->errors['name'] = "Unable to register user with provided data.";
}
return $this->errors;
}
public function validateSignup(): bool {
$this->errors = [];
if (empty($this->name) || (strlen($this->name) < 4)) {
$this->errors['name'] = "Username must be at least 4 characters.";
}
if (empty($this->email) || (filter_var($this->email, FILTER_VALIDATE_EMAIL) === false)) {
$this->errors['email'] = "Email address is required.";
}
if (empty($this->password) || strlen($this->password) < 6) {
$this->errors['password'] = "Password is required.";
}
If(count($this->errors) > 0) {
return empty($this->errors);
}
## after it checks validation with no errors check if already exists
if ($this->name) Helpers::alreadyExists("user", "name", $this->name) {
$this->errors['name'] = "Unable to register user with provided data.";
}
return empty($this->errors);
}
Related
I cannot figure out why my nesting here is not working. Whenever I run this it goes straight to 'Incorrect password' (with all the fields blank) even though the condition about string length that proceeds it, is false. A reading of 'Email and password are required' is what I want to happen first. THEN if the email doesn't contain an # sign, the # notification, THEN the password notification. But it keeps jumping over my previous if statements. I know the nesting must be wrong, and I've re-arranged it many times. The only way it works is to remove the # verification line completely, but I need to have it.
if ( isset($_POST['who']) && isset($_POST['pass']) ) {
if ( strlen($_POST['who']) < 1 || strlen($_POST['pass']) < 1 ) {
$failure = "E-mail and password are required";
}
if(stripos($_POST['who'],'#') === false && strlen($_POST['who'] > 1)) {
$failure = "E-mail must have an at-sign (#)";
}
else {
$check = hash('md5', $salt.$_POST['pass']);
if ( $check == $stored_hash ) {
// Redirect the browser to auto.php
header("Location: auto.php?name=".urlencode($_POST['who']));
return;
} else {
$failure = "Incorrect password";
}
}
}
you need to put 2nd if condition in else block. think about when password was blank but email was entered. it will bypass 2nd if block and go to else use like blow code
if ( isset($_POST['who']) && isset($_POST['pass']) ) {
if ( strlen($_POST['who']) <= 1 || strlen($_POST['pass']) < 1 ) {
$failure = "E-mail and password are required";
}
else {
if(stripos($_POST['who'],'#') === false && strlen($_POST['who'] > 1)) {
$failure = "E-mail must have an at-sign (#)";
}
else {
$check = hash('md5', $salt.$_POST['pass']);
if ( $check == $stored_hash ) {
// Redirect the browser to auto.php
header("Location: auto.php?name=".urlencode($_POST['who']));
return;
} else {
$failure = "Incorrect password";
}
}
}
}
I use OOP and i wanted to ask you guys how this would be done! I keep trying but its still not working ;(
Here is my class file:
class Signup {
// Error
public $error = array();
public function validate($username, $email_mobile, $password) {
if(!empty($username) || !empty($email_mobile) || !empty($password)){
if(strlen($username) < 3 || strlen($username) > 50){
$this->error = "Username is too short or too long!";
return $this->error;
}elseif(strlen($email_mobile) < 3 || strlen($email_mobile) > 50) {
$this->error = "Email is too short or too long!";
return $this->error;
}elseif(strlen($password) < 3 || strlen($password) > 50){
$this->error = "Password is too short or too long!";
return $this->error;
}
} else {
$this->error = "Please fill are required feilds";
return $this->error;
}
}
Here is my signup file
$error[] = $signup->validate($username, $email_mobile, $password);
<?php
// require('lib/function/signup.php');
if(isset($error)){
var_dump($error);
foreach ($error as $value) {
echo $value . "<br>";
}
}
?>
I know That im calling the $error in the same file and not the property error. But i dont know how to send this array to the other file! Please help me! Also i have Called everything and the problem is just with my code(i think), i only included my file and made a var to call my signup class
It is never too early in your development career to study coding standards. Jump straight to PSR-12, and adopt all of these guidelines to write beautiful, professional code.
Use data type declarations in your classes where possible, it will improve the data integrity throughout your project(s).
You appear to prefer returning an array of errors. For this reason, I see no benefit in caching the errors long-term in a class property. This coding style is fine to do, but you could choose to return nothing (void) and instead populate a class property $errors, then access it directly after the $signup->validate() call via $signup->errors or use a getter method.
The empty() checks are too late in the flow. Once the values have been passed to the class method, these values must already be declared. For this reason empty() is needless overhead to check for mere "falsiness". Just check the values' string length.
Your data quality checks seem a little immature (email and password checks should be much more complex), but I won't confuse you with any new complexity, but I do expect that your validation rules will increase as you realize that users cannot be trusted to put good values in forms without be forced to do so. For this reason, it is probably unwise to use a loop to check the value lengths because you will eventually need to write individual rules for certain values.
A possible write up:
class Signup
{
public function validate(
string $username,
string $email,
string $password
): array
{
$errors = [];
$usernameLength = strlen($username);
if ($usernameLength < 3 || $usernameLength > 50) {
$errors[] = "Username must be between 3 and 50 characters";
}
$emailLength = strlen($email);
if ($emailLength < 3 || $emailLength > 50) {
$errors[] = "Email must be between 3 and 50 characters";
}
$passwordLength = strlen($password);
if ($passwordLength < 3 || $passwordLength > 50) {
$errors[] = "Password must be between 3 and 50 characters";
}
return $errors;
}
}
When calling this method...
$signup = new Signup();
$errors = $signup->validate(
$_POST['username'] ?? '',
$_POST['email'] ?? '',
$_POST['password'] ?? ''
);
if ($errors) {
echo '<ul><li>' . implode('</li><li>', $errors) . '</li></ul>';
} else {
echo 'No errors';
}
You should add elements to the array, instead of overwriting it, and returning, on all the branches.
class Signup {
public $errors = [];
public function validate($username, $email_mobile, $password) {
if (empty($username)) {
$this->error[] = "Username cannot be empty";
} else {
$strlenUsername = strlen($username);
if ($strlenUsername < 3 || $strlenUsername > 50){
$this->errors[] = "Username is too short or too long!";
}
}
if (empty($email_mobile)) {
$this->error[] = "Email cannot be empty";
} else {
$strlenEM = strlen($email_mobile);
if ($strlenEM < 3 || $strlenEM > 50) {
$this->errors[] = "Email is too short or too long!";
}
}
if (empty($password)) {
$this->errors[] = "Password cannot be empty";
} else {
$strlenPass = strlen($password);
if ($strlenPass < 3 || $strlenPass > 50) {
$this->errors[] = "Password is too short or too long!";
}
}
return $this->errors;
}
}
If you always keep the same constrains for the three fields, you can shorten it:
class Signup {
public function validate($username, $email_mobile, $password) {
$errors = [];
$fields = [
'Username' => $username,
'Email' => $email_mobile,
'Password' => $password
];
foreach($fields as $key => $value) {
if (empty($value)) {
$errors[] = "$key cannot be empty";
} else {
$strlen = strlen($value);
if ($strlen < 3 || $strlen > 50) {
$errors[] = "$key is too short or too long!";
}
}
}
return $errors;
}
}
The above code guesses at what you are trying to do, if you just wanted a fix for not getting any results on $error see the original answer below.
Original answer.
Updating your code to this should give you the results you expect.
class Signup {
// Error
public $error = array();
public function validate($username, $email_mobile, $password) {
if (!empty($username) || !empty($email_mobile) || !empty($password)){
$strlenUsername = strlen($username);
$strlenEM = strlen($email_mobile);
$strlenPass = strlen($password);
if ($strlenUsername < 3 || $strlenUsername > 50){
$this->error[] = "Username is too short or too long!";
} elseif ($strlenEM < 3 || $strlenEM > 50) {
$this->error[] = "Email is too short or too long!";
} elseif ($strlenPass < 3 || $strlenPass > 50){
$this->error[] = "Password is too short or too long!";
}
} else {
$this->error[] = "Please fill are required feilds";
}
return $this->error;
}
}
Keep in mind that, since you are using if-else you will always have, at most, one element in the array, it is hard to tell what you are trying to do with certainty, so I didn't change the logic and just fixed the most obvious problem.
If you want to add error messages to the array, get rid of the else keyword on the conditionals.
If you want to only receive one error message, consider using a string instead of an array.
I have this php code associated with a database and I need here to make a complete email and name validation
based on this code how can I do that because my code has some issues here
1)name key doesn't have (//) or any symbols to be a correct name
2)email key is valid email because what we did here just make ensure that there is # symbol and if I type the email hhhh#hhh.com or even without( .com ) it will be valid also ?!!
if(array_key_exists("submit",$_POST)){
$link = mysqli_connect("localhost","root","123456789","users");
if(mysqli_connect_error()){
die("There is a problem in connecting to database");
}
if(!$_POST['name']){
$error .="<p>Your Full name is required</p><br>";
}
if(!$_POST['email']){
$error .="<p>Your email address is required</p><br>";
}
if(!$_POST['password']){
$error .="<p>Your password is required</p><br>";
}
if($error !=""){
$error = "<p>There were errors in your form</p><br>".$error;
}
}
You can use this function for the validation:
function filtervariable($string,$type,$method) {
//function for sanitizing variables using PHPs built-in filter methods
$validEmail = false;
if ($method == 'sanitize') {
$filtermethod = 'FILTER_SANITIZE_';
} elseif ($method == 'validate') {
$filtermethod = 'FILTER_VALIDATE_';
} else {
return;
}
switch ($type) {
case 'email':
case 'string':
case 'number_int':
case 'int':
case 'special_chars':
case 'url':
$filtertype = $filtermethod.strtoupper($type);
break;
}
if ($filtertype == 'FILTER_VALIDATE_EMAIL' && !empty($string)) {
list($local,$domain) = explode('#',$string);
$localLength = strlen($local);
$domainLength = strlen($domain);
$checkLocal = explode('.',$domain);
if (($localLength > 0 && $localLength < 65) && ($domainLength > 3 && $domainLength < 256) && (checkdnsrr($domain,'MX') || checkdnsrr($domain,'A') || ($checkLocal[1] == 'loc' || $checkLocal[1] == 'dev' || $checkLocal[1] == 'srv'))) { // check for "loc, dev, srv" added to cater for specific problems with local setups
$validEmail = true;
} else {
$validEmail = false;
}
}
if (($filtertype == 'FILTER_VALIDATE_EMAIL' && $validEmail) || $filtertype != 'FILTER_VALIDATE_EMAIL') {
return filter_var($string, constant($filtertype));
} else {
return false;
}
}
And use it like this:
$email = filtervariable($registeremail,'email','validate');
It will return "true" on success and "false" on failure.
<?php
class Validator {
public $errors = array(
'password' => '',
'email' => '');
const PASSWORD_MINCHARS = 8;
public function checkEmail($email) {
if ($this->checkEmpty($email)) {
if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
$this->errors['email'] = "Please provide a valid email";
return FALSE;
} else {
return TRUE;
}
} else {
$this->errors['email'] = "Please provide a value for the email";
return FALSE;
}
}
public function checkPassword($string) {
if ($this->checkEmpty($string)) {
if (strlen($string) < self::PASSWORD_MINCHARS) {
$this->errors['password'] = "The password should be atleast ".self::PASSWORD_MINCHARS." characters long.";
return FALSE;
} else {
return TRUE;
}
} else {
$this->errors['password'] = "Please provide a value for the password";
return FALSE;
}
}
private function checkEmpty($string) {
if (!empty($string)) {
return TRUE;
}
return FALSE;
}
public function displayErrors() {
$output = '';
foreach ($this->errors as $error) {
if (!empty($error)) {
$output .= '<p>'.$error.'</p>';
}
}
return $output;
}
}
?>
<?php
require 'Validator.php';
$validator = new Validator();
$email = '';
$password = '';
if ($validator->checkPassword($password) && $validator->checkEmail($email)) {
echo 'You have entered a valid password and email.';
} else {
echo $validator->displayErrors();
}
?>
The above code comes from two separate files. The one that comes begins with class Validator comes from Validator.php while the one that begins with the require function comes from index.php. So am just wondering why the method call that is $validator->displayErrors() in index.php only displays one error at a time instead of displaying them all at once.
There is only one error displayed because of your condition:
if ($validator->checkPassword($password) && $validator->checkEmail($email))
It executes your checkPassword method first, it returns false and so the second condition (which should execute the second validation method) is never checked.
You can avoid this by executing the validation methods first:
$validPassword = $validator->checkPassword($password);
$validEmail = $validator->checkEmail($email);
if ($validPassword && $validEmail) {
echo 'You have entered a valid password and email.';
} else {
echo $validator->displayErrors();
}
Replace
if ($validator->checkPassword($password) && $validator->checkEmail($email))
with
if ($validator->checkPassword($password) || $validator->checkEmail($email)) {
I'm trying to validate my username as an email address, however PHP isn't letting me do this! what's wrong here?
//This checks if all the fields are filled or not
if (!empty($_POST['username']) ||
!empty($_POST['password']) ||
!empty($_POST['repassword']) ||
!empty($_POST['user_firstname']) ||
!empty($_POST['user_lastname']) ){
header('Location: register.php?msg=You didn\'t complete all of the required fields');
}
if (filter_var($_POST['username'], FILTER_VALIDATE_EMAIL) === false){
$errors[] = 'The email address you entered is not valid';
}
here is the form i used in register.php
<form action="createuser.php" method="post" name="registration_form" id="registration_form">
<label>Email</label>
<input name="username" type="text" id="username" size="50" maxlength="50" /><br />
Typo?
header('Location: register.php?msg=You didn't complete all of the required fields');
^---unescaped embedded quote
Your empty logic is also faulty. You're checking if any fields are NOT empty (e.g. filled out) and then complaining that they're not filled out. remove the ! to invert the logic.
if (empty(...) || empty(...) || etc...)
instead of this use regular expression for validating your email address
function check_email_address($email) {
// First, we check that there's one # symbol,
// and that the lengths are right.
if (!preg_match("^[^#]{1,64}#[^#]{1,255}$", $email)) {
// Email invalid because wrong number of characters
// in one section or wrong number of # symbols.
return false;
}
// Split it into sections to make life easier
$email_array = explode("#", $email);
$local_array = explode(".", $email_array[0]);
for ($i = 0; $i < sizeof($local_array); $i++) {
if
(!preg_match("^(([A-Za-z0-9!#$%&'*+/=?^_`{|}~-][A-Za-z0-9!#$%&
↪'*+/=?^_`{|}~\.-]{0,63})|(\"[^(\\|\")]{0,62}\"))$",
$local_array[$i])) {
return false;
}
}
// Check if domain is IP. If not,
// it should be valid domain name
if (!preg_match("^\[?[0-9\.]+\]?$", $email_array[1])) {
$domain_array = explode(".", $email_array[1]);
if (sizeof($domain_array) < 2) {
return false; // Not enough parts to domain
}
for ($i = 0; $i < sizeof($domain_array); $i++) {
if
(!preg_match("^(([A-Za-z0-9][A-Za-z0-9-]{0,61}[A-Za-z0-9])|
↪([A-Za-z0-9]+))$",
$domain_array[$i])) {
return false;
}
}
}
return true;
}
and then check if it return true redirect it to location if not then simply throw an error
You would not get to Validate the email because your if statement is wrong .. it is checking if any of the post is not empty.
Replace it with
if (empty($_POST['username']) || empty($_POST['password']) || empty($_POST['repassword']) || empty($_POST['user_firstname']) || empty($_POST['user_lastname'])) {
For starters, look at the syntax highlighting for why you're getting parse errors.
header('Location: register.php?msg=You didn't complete all of the required fields');
needs to become:
header('Location: register.php?msg=You didn\'t complete all of the required fields');
How about you use javascript window.location? Sometimes header function is sensitive.And also put a submit button in your form since by default fields are empty when loaded.
if(isset($_POST['your_submit_button_name'])){
if (empty($_POST['username']) ||
empty($_POST['password']) ||
empty($_POST['repassword']) ||
empty($_POST['user_firstname']) ||
empty($_POST['user_lastname']) ){
?>
<script>
window.location = 'register.php?msg=You didn\'t complete all of the required fields';
</script>
<?php
}
if (filter_var($_POST['username'], FILTER_VALIDATE_EMAIL) === false){
$errors[] = 'The email address you entered is not valid';
}
}
NOTE: I remove "!" before your empty function since youre trapping the fields that are empty.
Try to use this solution:
$FormData = $_POST;
if(isset($FormData['button_name'])){
$Errors = array();
foreach ($$FormData as $key => $value) {
if(empty($value)) $Errors[] = 'Some message';
if($key = 'username'){
if(filter_var($value, FILTER_VALIDATE_EMAIL){
$Errors[] = 'The email address you entered is not valid';
}
}
}
if(empty($Errors)){
// #todo Do some action
} else {
header('Location: register.php?msg=You didn\'t complete all of the required fields');
}
}
function check_email($check) {
$expression = "/^[a-zA-Z0-9._-]+#[a-zA-Z0-9._-]+\.([a-zA-Z]{2,4})$/";
if (preg_match($expression, $check)) {
return true;
} else {
return false;
}
}
Now use this method as :
if(!check_email($_REQUEST['ContactEmail'])){
$register_error .="Enter the correct email address!<br />";
$reg_error=1;
}