Server-side validation not checking the next field in php - php

I have a login page with two radio button(buyer or seller)
For example, I chose buyer the I will get a login field
Mobile
Password
Or, I chose seller the I will get a login field
Email
Password
I am using the below function for the login code.
function login($pdo){
$account_type=sanitize_data($_POST['account_type']);
$password =sanitize_data($_POST['password']);
if (empty($account_type)) {
$errorMsg= "Please select account type";
$code= "1" ;
}
elseif ($account_type==1) {
$mobileno=sanitize_data($_POST['mobileno']);
if(empty($mobileno)) {
$errorMsg= "Please enter mobile number.";
$code= "2";
}
elseif(is_numeric(trim($mobileno)) == false){
$errorMsg= "Please enter numeric value.";
$code= "2";
}elseif(strlen($mobileno)<10){
$errorMsg= "Number should be ten digits.";
$code= "2";
}
else{
// echo "<pre>";
echo "4";// getting issue here
}
}
elseif ($account_type==2) {
if(empty($email)){
$errorMsg="You did not enter a email.";
$code="2";
} //check for valid email
elseif(filter_var($email, FILTER_VALIDATE_EMAIL) === false){
$errorMsg= "You did not enter a valid email.";
$code="2";
}
else{
}
}
elseif( empty($password)) {
$errorMsg= "Please enter the password";
$code="3";
}
else{
try{
//query here
} catch(PDOExecption $e) {
$dbh->rollback();
print "Error!: " . $e->getMessage() . "</br>";
}
}
}
Now, I am getting issues in nested if condition.
For example, I choose buyer and I added 10 digits mobile number and submitted the form.
According to my code, it should check the server side validation for the field like the password is entered or not. right?
But it stops. I mean if the server-side validation is clear for mobile then it should check the next one but it's not checking.
I mean it's not checking the password. I think my execution is stopped once reach the else part.
elseif ($account_type==1) {
$mobileno=sanitize_data($_POST['mobileno']);
if(empty($mobileno)) {
$errorMsg= "Please enter mobile number.";
$code= "2";
}
elseif(is_numeric(trim($mobileno)) == false){
$errorMsg= "Please enter numeric value.";
$code= "2";
}elseif(strlen($mobileno)<10){
$errorMsg= "Number should be ten digits.";
$code= "2";
}
else{
// echo "<pre>";
echo "4"; // getting issue here
}
}
are the right way to use the code for login and server-side validation?

Actually, it's the outer clause that causes your issues. It reads like this:
if (empty($account_type)) {
// We don't have an account type.
}
elseif ($account_type==1) {
// Account type is '1'. Proceed in here.
}
elseif ($account_type==2) {
// Account type is '2'.
}
elseif(empty($password)) {
// We don't have a password.
}
else {
// We have a password and an account type,
// and it's neither 1 nor 2.
try {
...
} catch(PDOExecption $e) {
...
}
}
I'd suggest splitting your if chains - to be able to do this, though, you might also need to re-structure your sanitation, validation and error handling.
Wrapping your logic in a class might be worth a thought, for example:
// Mock db
class DbConnection {}
class Login {
/**
* #var Array
*/
protected $error;
/**
* #var Array
*/
protected $data;
/**
* #var DbConnection
*/
protected $db;
/**
* Mock sanitizing
*/
protected function sanitize(array $data): array {
return $data;
}
protected function validate(): bool {
// In our sanitize() method, we already made sure
// that everything we need is set, so we don't have
// to do it here.
$account_type = $this->data['account_type'];
$password = $this->data['password'];
// Return early if we don't have an account type or
// a password.
if (!$account_type) {
$this->error = [1, 'Please select account type'];
return false;
}
if(!$password) {
$this->error = [3, 'Please provide a password'];
return false;
}
if ($account_type == 1) {
$mobileno = $this->data['mobileno'];
// We might already have stripped everything that's not a number
// from our mobile number string when sanitizing it, so we already
// made sure it's either empty or numeric.
//
// To validate it, we could either use a regex, or one of the PHP
// ports of Google's libphonenumber library:
// - https://stackoverflow.com/questions/123559/how-to-validate-phone-numbers-using-regex
// - https://stackoverflow.com/questions/22378736/regex-for-mobile-number-validation/
// - https://github.com/giggsey/libphonenumber-for-php
//
// Let's assume we already used one of those methods, so the value of
// $mobileno would be either valid or false.
if (!$mobileno) {
$this->error = [2, 'Please enter a valid mobile number'];
return false;
}
return true;
}
if ($account_type==2) {
// Some validation logic. If nothing fails, we'll finally return true.
return true;
}
}
/**
* #return Mixed - Boolean|User (object, array...)
*/
public function login() {
if (!$this->validate()) {
return false;
}
$password = $this->data['password'];
try {
// Query db for password (and maybe a username, too)
return ['User' => '...'];
}
catch(PDOExecption $e) {
// Exception handling;
}
}
public function getError() {
return $this->error;
}
public function __construct(array $data, DbConnection $db) {
$this->data = $this->sanitize($data);
$this->db = $db;
}
}
You're login process would then be:
// Mock POST data
$_POST = [
'account_type' => '1',
'password' => 'PwG2c?4tyUzEtD!9',
'mobileno' => '012345678986'
];
// Evaluate login attempt
$attempt = new Login($_POST, new DbConnection());
$user = $attempt->login();
if (!$user) {
var_dump($attempt->getError());
}
else {
var_dump($user);
}
Sources used:
How to validate phone numbers using regex
Regex for Mobile Number Validation
https://github.com/giggsey/libphonenumber-for-php

Related

Why does the validation email returns an error?

I am developing a Register/Login system with validation. Registering system is working well. For example, when I register the same email twice, the following message appears:
Email already registered!
However, when I log-in with the same e-mail and password, an error occurs. The following message appears as a validation error:
Email not registered!
Even if the email is registered in DB.
Code for e-mail validation:
<?php
public function validateEmail($par)
{
if (filter_var($par, FILTER_VALIDATE_EMAIL)) {
return true;
} else {
$this->setErro("Invalid Email!");
return false;
}
}
public function validateIssetEmail($email, $action = null)
{
$b = $this->cadastro->getIssetEmail($email);
if ($action == null) {
if ($b > 0) {
$this->setErro("Email already registered!");
return false;
} else {
return true;
}
} else {
if ($b > 0) {
return true;
} else {
$this->setErro("Email not registered!");
return false;
}
}
}
Code for login controller:
<?php
$validate = new Classes\ClassValidate();
$validate->validateFields($_POST);
$validate->validateEmail($email);
$validate->validateIssetEmail($email,"login");
$validate->validateStrongSenha($senha);
$validate->validateSenha($email,$senha);
var_dump($validate->getErro());
Code for class login:
<?php
namespace Models;
class ClassLogin extends ClassCrud
{
# Returns user data
public function getDataUser($email)
{
$b = $this->selectDB(
"*",
"users",
"where email=?",
array(
$email
)
);
$f = $b->fetch(\PDO::FETCH_ASSOC);
$r = $b->rowCount();
return $arrData = [
"data" => $f,
"rows" => $r
];
}
}
My getIssetEmail method exists on Register code only.
# Check directly at the bank if the email is registered
public function getIssetEmail($email)
{
$b = $this->selectDB(
"*",
"users",
"where email=?",
[
$email
]
);
return $r = $b->rowCount(); // returns the amount of rows in the search
}
And ClassPassword
<?php
namespace Classes;
use Models\ClassLogin;
class ClassPassword
{
private $db;
public function __construct()
{
$this->db = new ClassLogin();
}
# Create password's hash to save in DB
public function passwordHash($senha)
{
return password_hash($senha, PASSWORD_DEFAULT);
}
# Verify if password's hash is correct
public function verifyHash($email, $senha)
{
$hashDb = $this->db->getDataUser($email);
return password_verify($senha, $hashDb["data"]["senha"]);
}
}
This is not an answer but hopefully it will help in debugging.
First, I'm going to change your code. This is 100% a style choice but I personally think it is easier to follow. If you have an if statement that always returns, you don't technically need an else. Once again, this is a style choice and you don't have to follow it.
Second, if you can, try adding logging into your workflow, it will save you so much time debugging. It isn't always an option, especially for legacy code bases, but it is awesome when you can inspect complex code. In this example, I"m just making a couple of helper methods that dump stuff but normally I'd use something like Monolog to write to a stream that I can tail, and I can easily turn it off in production. When logging, sometimes it helps to avoid identical messages so that you can easily find the exact line number you are on, too.
So with those changes, try running this code inside of your class:
private function logMessage($message)
{
echo $message . PHP_EOL;
}
private function logVariable($variable)
{
var_dump($variable);
}
public function validateIssetEmail($email, $action = null)
{
$this->logVariable($email);
$this->logVariable($action);
$b = $this->cadastro->getIssetEmail($email);
$this->logVariable($b);
if ($action === null) {
$this->logMessage('Action was null');
if ($b > 0) {
$this->logMessage('B is greater than zero');
$this->setErro("Email already registered!");
return false;
}
$this->logMessage('B was not greater than zero');
return true;
}
$this->logMessage('Action was not null');
if ($b > 0) {
$this->logMessage('B is greater than zero');
return true;
}
$this->logMessage('B was not greater than zero');
$this->setErro("Email not registered!");
return false;
}
This should log in human-readable form every step. You should be able to walk through this and identify where your bug is. For instance, in the comments above you said that a variable was 0 in a block that was guarded by a check that guarantees that that shouldn't happen.
This is the wrong part i guess you assigned login as action so you can call cadastro class inside of the function
$cadastro = new Cadastro();
$b = $cadastro->getIssetEmail($email);
if ($action == null) {
if ($b > 0) {
$this->setErro("Email already registered!");
return false;
} else {
return true;
}
} else {
if ($b > 0) {
return true;
} else {
$this->setErro("Email not registered!");
return false;
}
}

Displaying multiple exception messages in PHP

So I'm making this login-app, and I've got troubles displaying the correct error-messages upon register. I want all the exceptions to be thrown and not just one exception in a "try...catch"-method.
So this is the setup:
// EXTENDED EXCEPTION CLASSES
class AException extends Exception {
public function __construct($message = null, $code = 0) {
echo $message;
}
}
class BException extends Exception {
public function __construct($message = null, $code = 0) {
echo $message;
}
}
// INDEX.PHP
try {
$register = new RegisterController();
} catch (AException | BException $e) {
$e->getMsg();
}
I have several factors that may trigger the exception, and I would like all the exceptions to be triggered and captured e.g. if the register form was posted empty, there should be one exception for username being empty, another exception for password being empty etc..
class RegisterController {
public function __construct() {
if (!empty($_POST)) {
$this->checkUserInput();
$this->checkPassInput();
}
}
//... executing code
private function checkUserInput() {
if (strlen($_POST['username']) < 3) { // check character length bigger than 3
throw new \AException("Username has too few characters.");
}
}
private function checkPassInput() {
if (strlen($_POST['password']) < 3) { // check character length bigger than 3
throw new \BException("Password has too few characters.");
}
}
}
So, how do I make my "try...catch"-method echo both the thrown exceptions? Is it possible?
Right now only the first thrown exception-message is displayed, so I guess I need to find some way for the script to continue after an exception has been thrown...
P.S. To clarify further: if a register form is posted with empty input-fields e.g. both username and password input is empty, I want the code to echo two exception-messages, both "Username has too few characters." and "Password has too few characters.".
That's not how the try/catch mechanism is supposed to work. It is not meant to report notices to end users, but to programmatically take action if an undesired situation occurs.
What you want is a simple form validation:
class RegisterController {
public $errors = [];
public function __construct() {
if (!empty($_POST)) {
$this->checkUserInput();
$this->checkPassInput();
}
private function checkUserInput() {
if (strlen($_POST['username']) < 3) { // check character length bigger than 3
$this->errors[] = "Username has too few characters.";
}
}
private function checkPassInput() {
if (strlen($_POST['password']) < 3) { // check character length bigger than 3
$this->errors[] = "Password has too few characters.";
}
}
}
Then you can use something like:
$register = new RegisterController();
if (!empty($register->errors)) {
foreach ($register->errors as $error) {
echo '<div class="error">' . $error . '</div>';
}
}

No Database Login Form PHP

Can you help me make a code for PHP login no db.
Thanks in advance
Link to Login Form
[Sorry for pastebin link because i'm new to stackover flow]
Here you gone...done!
github.com/panique/php-login-one-file
<?php
/**
* Class OneFileLoginApplication
*
* An entire php application with user registration, login and logout in one file.
* Uses very modern password hashing via the PHP 5.5 password hashing functions.
* This project includes a compatibility file to make these functions available in PHP 5.3.7+ and PHP 5.4+.
*
* #author Panique
* #link https://github.com/panique/php-login-one-file/
* #license http://opensource.org/licenses/MIT MIT License
*/
class OneFileLoginApplication
{
/**
* #var string Type of used database (currently only SQLite, but feel free to expand this with mysql etc)
*/
private $db_type = "sqlite"; //
/**
* #var string Path of the database file (create this with _install.php)
*/
private $db_sqlite_path = "./users.db";
/**
* #var object Database connection
*/
private $db_connection = null;
/**
* #var bool Login status of user
*/
private $user_is_logged_in = false;
/**
* #var string System messages, likes errors, notices, etc.
*/
public $feedback = "";
/**
* Does necessary checks for PHP version and PHP password compatibility library and runs the application
*/
public function __construct()
{
if ($this->performMinimumRequirementsCheck()) {
$this->runApplication();
}
}
/**
* Performs a check for minimum requirements to run this application.
* Does not run the further application when PHP version is lower than 5.3.7
* Does include the PHP password compatibility library when PHP version lower than 5.5.0
* (this library adds the PHP 5.5 password hashing functions to older versions of PHP)
* #return bool Success status of minimum requirements check, default is false
*/
private function performMinimumRequirementsCheck()
{
if (version_compare(PHP_VERSION, '5.3.7', '<')) {
echo "Sorry, Simple PHP Login does not run on a PHP version older than 5.3.7 !";
} elseif (version_compare(PHP_VERSION, '5.5.0', '<')) {
require_once("libraries/password_compatibility_library.php");
return true;
} elseif (version_compare(PHP_VERSION, '5.5.0', '>=')) {
return true;
}
// default return
return false;
}
/**
* This is basically the controller that handles the entire flow of the application.
*/
public function runApplication()
{
// check is user wants to see register page (etc.)
if (isset($_GET["action"]) && $_GET["action"] == "register") {
$this->doRegistration();
$this->showPageRegistration();
} else {
// start the session, always needed!
$this->doStartSession();
// check for possible user interactions (login with session/post data or logout)
$this->performUserLoginAction();
// show "page", according to user's login status
if ($this->getUserLoginStatus()) {
$this->showPageLoggedIn();
} else {
$this->showPageLoginForm();
}
}
}
/**
* Creates a PDO database connection (in this case to a SQLite flat-file database)
* #return bool Database creation success status, false by default
*/
private function createDatabaseConnection()
{
try {
$this->db_connection = new PDO($this->db_type . ':' . $this->db_sqlite_path);
return true;
} catch (PDOException $e) {
$this->feedback = "PDO database connection problem: " . $e->getMessage();
} catch (Exception $e) {
$this->feedback = "General problem: " . $e->getMessage();
}
return false;
}
/**
* Handles the flow of the login/logout process. According to the circumstances, a logout, a login with session
* data or a login with post data will be performed
*/
private function performUserLoginAction()
{
if (isset($_GET["action"]) && $_GET["action"] == "logout") {
$this->doLogout();
} elseif (!empty($_SESSION['user_name']) && ($_SESSION['user_is_logged_in'])) {
$this->doLoginWithSessionData();
} elseif (isset($_POST["login"])) {
$this->doLoginWithPostData();
}
}
/**
* Simply starts the session.
* It's cleaner to put this into a method than writing it directly into runApplication()
*/
private function doStartSession()
{
if(session_status() == PHP_SESSION_NONE) session_start();
}
/**
* Set a marker (NOTE: is this method necessary ?)
*/
private function doLoginWithSessionData()
{
$this->user_is_logged_in = true; // ?
}
/**
* Process flow of login with POST data
*/
private function doLoginWithPostData()
{
if ($this->checkLoginFormDataNotEmpty()) {
if ($this->createDatabaseConnection()) {
$this->checkPasswordCorrectnessAndLogin();
}
}
}
/**
* Logs the user out
*/
private function doLogout()
{
$_SESSION = array();
session_destroy();
$this->user_is_logged_in = false;
$this->feedback = "You were just logged out.";
}
/**
* The registration flow
* #return bool
*/
private function doRegistration()
{
if ($this->checkRegistrationData()) {
if ($this->createDatabaseConnection()) {
$this->createNewUser();
}
}
// default return
return false;
}
/**
* Validates the login form data, checks if username and password are provided
* #return bool Login form data check success state
*/
private function checkLoginFormDataNotEmpty()
{
if (!empty($_POST['user_name']) && !empty($_POST['user_password'])) {
return true;
} elseif (empty($_POST['user_name'])) {
$this->feedback = "Username field was empty.";
} elseif (empty($_POST['user_password'])) {
$this->feedback = "Password field was empty.";
}
// default return
return false;
}
/**
* Checks if user exits, if so: check if provided password matches the one in the database
* #return bool User login success status
*/
private function checkPasswordCorrectnessAndLogin()
{
// remember: the user can log in with username or email address
$sql = 'SELECT user_name, user_email, user_password_hash
FROM users
WHERE user_name = :user_name OR user_email = :user_name
LIMIT 1';
$query = $this->db_connection->prepare($sql);
$query->bindValue(':user_name', $_POST['user_name']);
$query->execute();
// Btw that's the weird way to get num_rows in PDO with SQLite:
// if (count($query->fetchAll(PDO::FETCH_NUM)) == 1) {
// Holy! But that's how it is. $result->numRows() works with SQLite pure, but not with SQLite PDO.
// This is so crappy, but that's how PDO works.
// As there is no numRows() in SQLite/PDO (!!) we have to do it this way:
// If you meet the inventor of PDO, punch him. Seriously.
$result_row = $query->fetchObject();
if ($result_row) {
// using PHP 5.5's password_verify() function to check password
if (password_verify($_POST['user_password'], $result_row->user_password_hash)) {
// write user data into PHP SESSION [a file on your server]
$_SESSION['user_name'] = $result_row->user_name;
$_SESSION['user_email'] = $result_row->user_email;
$_SESSION['user_is_logged_in'] = true;
$this->user_is_logged_in = true;
return true;
} else {
$this->feedback = "Wrong password.";
}
} else {
$this->feedback = "This user does not exist.";
}
// default return
return false;
}
/**
* Validates the user's registration input
* #return bool Success status of user's registration data validation
*/
private function checkRegistrationData()
{
// if no registration form submitted: exit the method
if (!isset($_POST["register"])) {
return false;
}
// validating the input
if (!empty($_POST['user_name'])
&& strlen($_POST['user_name']) <= 64
&& strlen($_POST['user_name']) >= 2
&& preg_match('/^[a-z\d]{2,64}$/i', $_POST['user_name'])
&& !empty($_POST['user_email'])
&& strlen($_POST['user_email']) <= 64
&& filter_var($_POST['user_email'], FILTER_VALIDATE_EMAIL)
&& !empty($_POST['user_password_new'])
&& strlen($_POST['user_password_new']) >= 6
&& !empty($_POST['user_password_repeat'])
&& ($_POST['user_password_new'] === $_POST['user_password_repeat'])
) {
// only this case return true, only this case is valid
return true;
} elseif (empty($_POST['user_name'])) {
$this->feedback = "Empty Username";
} elseif (empty($_POST['user_password_new']) || empty($_POST['user_password_repeat'])) {
$this->feedback = "Empty Password";
} elseif ($_POST['user_password_new'] !== $_POST['user_password_repeat']) {
$this->feedback = "Password and password repeat are not the same";
} elseif (strlen($_POST['user_password_new']) < 6) {
$this->feedback = "Password has a minimum length of 6 characters";
} elseif (strlen($_POST['user_name']) > 64 || strlen($_POST['user_name']) < 2) {
$this->feedback = "Username cannot be shorter than 2 or longer than 64 characters";
} elseif (!preg_match('/^[a-z\d]{2,64}$/i', $_POST['user_name'])) {
$this->feedback = "Username does not fit the name scheme: only a-Z and numbers are allowed, 2 to 64 characters";
} elseif (empty($_POST['user_email'])) {
$this->feedback = "Email cannot be empty";
} elseif (strlen($_POST['user_email']) > 64) {
$this->feedback = "Email cannot be longer than 64 characters";
} elseif (!filter_var($_POST['user_email'], FILTER_VALIDATE_EMAIL)) {
$this->feedback = "Your email address is not in a valid email format";
} else {
$this->feedback = "An unknown error occurred.";
}
// default return
return false;
}
/**
* Creates a new user.
* #return bool Success status of user registration
*/
private function createNewUser()
{
// remove html code etc. from username and email
$user_name = htmlentities($_POST['user_name'], ENT_QUOTES);
$user_email = htmlentities($_POST['user_email'], ENT_QUOTES);
$user_password = $_POST['user_password_new'];
// crypt the user's password with the PHP 5.5's password_hash() function, results in a 60 char hash string.
// the constant PASSWORD_DEFAULT comes from PHP 5.5 or the password_compatibility_library
$user_password_hash = password_hash($user_password, PASSWORD_DEFAULT);
$sql = 'SELECT * FROM users WHERE user_name = :user_name OR user_email = :user_email';
$query = $this->db_connection->prepare($sql);
$query->bindValue(':user_name', $user_name);
$query->bindValue(':user_email', $user_email);
$query->execute();
// As there is no numRows() in SQLite/PDO (!!) we have to do it this way:
// If you meet the inventor of PDO, punch him. Seriously.
$result_row = $query->fetchObject();
if ($result_row) {
$this->feedback = "Sorry, that username / email is already taken. Please choose another one.";
} else {
$sql = 'INSERT INTO users (user_name, user_password_hash, user_email)
VALUES(:user_name, :user_password_hash, :user_email)';
$query = $this->db_connection->prepare($sql);
$query->bindValue(':user_name', $user_name);
$query->bindValue(':user_password_hash', $user_password_hash);
$query->bindValue(':user_email', $user_email);
// PDO's execute() gives back TRUE when successful, FALSE when not
// #link http://stackoverflow.com/q/1661863/1114320
$registration_success_state = $query->execute();
if ($registration_success_state) {
$this->feedback = "Your account has been created successfully. You can now log in.";
return true;
} else {
$this->feedback = "Sorry, your registration failed. Please go back and try again.";
}
}
// default return
return false;
}
/**
* Simply returns the current status of the user's login
* #return bool User's login status
*/
public function getUserLoginStatus()
{
return $this->user_is_logged_in;
}
/**
* Simple demo-"page" that will be shown when the user is logged in.
* In a real application you would probably include an html-template here, but for this extremely simple
* demo the "echo" statements are totally okay.
*/
private function showPageLoggedIn()
{
if ($this->feedback) {
echo $this->feedback . "<br/><br/>";
}
echo 'Hello ' . $_SESSION['user_name'] . ', you are logged in.<br/><br/>';
echo 'Log out';
}
/**
* Simple demo-"page" with the login form.
* In a real application you would probably include an html-template here, but for this extremely simple
* demo the "echo" statements are totally okay.
*/
private function showPageLoginForm()
{
if ($this->feedback) {
echo $this->feedback . "<br/><br/>";
}
echo '<h2>Login</h2>';
echo '<form method="post" action="' . $_SERVER['SCRIPT_NAME'] . '" name="loginform">';
echo '<label for="login_input_username">Username (or email)</label> ';
echo '<input id="login_input_username" type="text" name="user_name" required /> ';
echo '<label for="login_input_password">Password</label> ';
echo '<input id="login_input_password" type="password" name="user_password" required /> ';
echo '<input type="submit" name="login" value="Log in" />';
echo '</form>';
echo 'Register new account';
}
/**
* Simple demo-"page" with the registration form.
* In a real application you would probably include an html-template here, but for this extremely simple
* demo the "echo" statements are totally okay.
*/
private function showPageRegistration()
{
if ($this->feedback) {
echo $this->feedback . "<br/><br/>";
}
echo '<h2>Registration</h2>';
echo '<form method="post" action="' . $_SERVER['SCRIPT_NAME'] . '?action=register" name="registerform">';
echo '<label for="login_input_username">Username (only letters and numbers, 2 to 64 characters)</label>';
echo '<input id="login_input_username" type="text" pattern="[a-zA-Z0-9]{2,64}" name="user_name" required />';
echo '<label for="login_input_email">User\'s email</label>';
echo '<input id="login_input_email" type="email" name="user_email" required />';
echo '<label for="login_input_password_new">Password (min. 6 characters)</label>';
echo '<input id="login_input_password_new" class="login_input" type="password" name="user_password_new" pattern=".{6,}" required autocomplete="off" />';
echo '<label for="login_input_password_repeat">Repeat password</label>';
echo '<input id="login_input_password_repeat" class="login_input" type="password" name="user_password_repeat" pattern=".{6,}" required autocomplete="off" />';
echo '<input type="submit" name="register" value="Register" />';
echo '</form>';
echo 'Homepage';
}
}
// run the application
$application = new OneFileLoginApplication();

Password and verification is true altough one of them is not set.

i have some function for checking password is required and compare it with verification here's my function:
public function required($field= array())
{
foreach($field as $value) {
if (isset($this->_input[$value])) {
if (empty(Security::clean($this->_input[$value]))) {
$messages = "is Required.";
error::inputError($value, $messages);
}
} else{
$messages = "Not Found.";
error::inputError($field, $messages);
}
}
}
public function password($field, $confirmasion){
if (isset($this->_input[$field] , $this->_input[$confirmasion])){
if ($this->_input[$field] != $this->_input[$confirmasion])
{
$messages = "is different with $confirmasion.";
error::inputError($field, $messages);
error::inputError($confirmasion, $messages);
}
}
}
In my class $this->_input refers to $_POST. and then i have a class to set an error like this:
public static function inputError($field, $messages)
{
if (is_array($field)) {
foreach ($field as $key){
$newName = General::changeName($key);
$messagesError = "$newName $messages";
if (isset(self::$_errors[$key])){
return;
}else{
self::$_errors[$key] = $messagesError;
}
}
}else{
$newName = General::changeName($field);
$messagesError = "$newName $messages";
if (isset(self::$_errors[$field])){
return;
}else{
self::$_errors[$field] = $messagesError;
}
}
}
i'm expecting when when i submit form and my password and verification fields is empty it display "password is required" or "verification is required" only without showing error "password is different from verification”. but when i'm only fill my password fields it showing “verification is required“ and the second error "password is different different from verification” because my verification is still empty. Is it something wrong with my logic or something?
isset($this->_input['fieldname'])
this code will return true. Hence, having the verification field empty will still compare it to the password field.here's the solution:
(!empty($this->_input[$field]) && !empty($this->_input[$confirmasion]))

More professional error handling

I have a contact form and I handle errors by checking each field one-by-one with an "if" statement. I find this hard and I can't seem to find a better/more productive way to get them working. I would also like a heading saying "Error" if one (or more) is true. But I cant get them to work with the separate "if" statements.
Here is my code:
$name = $_POST['name']; //get data from the form
$email = $_POST['email'];//get data from the form
$message = $_POST['message'];//get data from the form
if($name == ""){
echo"<p class='error'>Please enter a name.</p>";
}
if (!eregi("^[_a-z0-9-]+(\.[_a-z0-9-]+)*#[a-z0-9-]+(\.[a-z0-9-]+)*(\.[a-z]{2,3})$",$email)){
echo "<p class='error'>Your email address is not valid.</p>";
}
if($message == ""){
echo"<p class='error'>Please enter a message.</p>";
}
else{
echo"all ok, send email code...";
}
Edit: These errors are for the validation of the form.
But I cant get them to work with the separate "if" statements.
Just store error in a variable
$error = array();
if($name == ""){
$error[] = "Please enter a name.";
}
if (!eregi("^[_a-z0-9-]+(\.[_a-z0-9-]+)*#[a-z0-9-]+(\.[a-z0-9-]+)*(\.[a-z]{2,3})$",$email)){
$error[] = "Your email address is not valid.";
}
if($message == ""){
$error[] = "Please enter a message.";
}
if (!$error) {
// do not echo anything here
// but send an email
// and use header("Location:") to redirect a user to thanks page
} else {
echo "Error";
foreach ($error as $line) {
echo "<p class='error'>$line</p>";
}
}
You are looking for validator class. Also see:
Building An Extensible Form Validator Class
The most professional way would be to have each field be an object with a validation method.
Then you can call each field object and ask them to validate themself.
If you would like to go any further (might be overkill though) you put your objects in a list.
Each of these objects are child to an interface with the validation method. So for each object in the list, you call the validation method.
Well, you can't check all fields together as different rules may apply to each one. So what you are doing is fine, except for a mistake you made: The else part should only be echoed, when no error occurred, but in your situation the else only applies to the last if. So even if the validation of name and email fails, as long as the message one does not, the final action is done.
You could easily add some $has_error variable that contains true as soon as an error was found. Or you could use an array that holds all error messages like this:
$errors = array();
if ( empty( $name ) )
$errors[] = 'Please enter a name.';
if ( !eregi("^[_a-z0-9-]+(\.[_a-z0-9-]+)*#[a-z0-9-]+(\.[a-z0-9-]+)*(\.[a-z]{2,3})$", $email ) )
$errors[] ='Your email address is not valid.';
if ( empty( $message ) )
$errors[] = 'Please enter a message.';
// individual checks done
if ( sizeof( $errors ) > 0 )
{
echo '<p class="error"><strong>Errors found:</strong><br />';
echo implode( '<br />', $errors );
echo '</p>';
}
else
{
echo 'No error, everything is fine.';
}
First, don't use ereg*() functions for regular expressions matching, these are deprecated and slow. Use the preg_*() functions instead.
Also take a look at PHP's filter extension.
It provides functions to check and validate various data which you can use directly or incorporate into your own validator functions.
EDIT: Example for checking an e-mail address (see also examples on php.net):
if ( !filter_var($email, FILTER_VALIDATE_EMAIL) ) {
echo 'Invalid e-mail "'.$email.'"';
Speaking of validation in an object-oriented manner, you could have a generic validator class with basic validation functions (where you could also integrate filter functions for a consistent API).
Additionally, if your data logically belongs together such that you can group them into objects and manage them as such, implement a validate() method in the classes of these objects that checks the object's properties by utilizing the filter functions and/or your validator class.
class Message {
private $name;
private $email;
private $text;
...
public function getName() {
return $this->name;
}
public function setName($name) {
$this->name = $name;
}
public function getEMail() {
return $this->email;
}
public function setEMail($email) {
$this->email = $email;
}
...
public function validate() {
$errors = array();
$nameLength = strlen($this->name);
if ( ($nameLength === 0) or ($nameLength > self::NAME_MAX_LENGTH) )
$errors['name'] = 'Name must be between 1 and '.self::NAME_MAX_LENGTH.' characters.';
if ( !Validator::isEMail($this->email) )
$errors['email'] = 'Invalid e-mail "'.$this->email.'"';
// Other checks
...
// Return TRUE if successful, otherwise array of errors
return ( count($errors) === 0 ? true : $errors );
}
}
Then, you could load all your form inputs into your object like this:
$message = new Message();
$message->setName($_POST['name']);
$message->setEMail($_POST['email']);
$message->setText($_POST['text']);
...
$result = $message->validate();
if ( $result === true ) {
// Success
} else {
// Error
foreach ($result as $validationError) {
// Print error
echo htmlentities($validationError).'<br />';
}
}

Categories