Passing variables out of a function - php

So, every page looks for 4 things, $e,$w,$n and $success.
$e is an array where errors are set. In every function errors are set with $e[] = 'error message';
Same for $w that is for warnings, $n for notices and the obvious for $success.
Now if the function has errors it shouldn't go ahead with the operations it's set to do, where as notices and warning are just for informing purposes.
The pages check for all of those and display each one in closeable coloured divs.
so here is my question...
I don't think this will work as expected.
Will this return the variable itself, or does this just show the contents of the variables when the function is run?
function add_member()
{
global $dbh;
if (!isset($_POST['username'],$_POST['password'],$_POST['email'])) {
$e[] = 'We need the minimum of a username and password to add a new user';
}
$regex = '/^[_a-z0-9-]+(\.[_a-z0-9-]+)*#[a-z0-9-]+(\.[a-z0-9-]+)*(\.[a-z]{2,3})$/';
if (!preg_match($regex, $_POST['email'])) {
$e[] 'The email address is wrong';
}
$stmt = $dbh->prepare("SELECT `username` FROM `1_members` WHERE `username`=? LIMIT 1");
$username = strtolower($_POST['username']);
$username = trim($username);
$stmt->bindValue(1, $username, PDO::PARAM_STR);
$stmt->execute();
if ($stmt->rowCount()) {
$e[] = 'That username is already in use';
}
if (($_POST['password']) !== ($_POST['vpassword'])) {
$e[] = 'The passwords did not match.';
}
if (strlen($_POST['username']) <= '3') {
$e[] = 'Username too short - needs to be 4 or more chars.';
}
if (strlen($_POST['password']) <='5'){
$e[] = 'password not long enough, please make it 6 chars.';
}
if (!isset($_POST['vpassword'])) {
$w[] = 'Warning: You didn\'t verify the password. Incase of typo the password was ['..']';
}
if (!isset($_POST['email'])) {
$w[] = 'Warning: You didn\'t enter an email address the password. This member will not get email alerts without an email address.';
}
if ($e) {
return $e;
}
else {
$password = trim($_POST['password']);
$options = ['cost' => 12,];
$password = password_hash($password, PASSWORD_BCRYPT, $options);
$email = trim($_POST['email']);
$stmt = $dbh->prepare("INSERT INTO `1_members` (`username`, `password`, `email`) VALUES(?,?,?)");
$stmt->bindValue(1,$username,PDO::PARAM_STR);
$stmt->bindValue(2,$password,PDO::PARAM_STR);
$stmt->bindValue(3,$email,PDO::PARAM_STR);
$stmt->execute()
$success = 'added member '.$username.'';
if (isset($w)) {
return $w;
}
if (isset($n)) {
return $n
}
return $success;
}
}

This function will return possibly 4 different things, and unless there is a massive error somewhere in the database setup, it shouldn't display anything. Instead, it'll return variables:
$e (array) if account can't be created due to a validation error or duplication
$w (array) if there is a warning after account creation
$n (array) if there is a notice after creation -- except that never happens. $n is not declared.
$success (string) otherwise
This function is all over the place - unpredictable. Whatever calls it will have to do a bunch of logic to deal with its return. Possibly a better way to do this is to return a richer construct. For example:
function add_member() {
$return_info = array(
"errors" => array(),
"warnings" => array(),
"notices" => array(),
"created" => false # sometimes a simple true / false is good enough
);
// do validation as before
// ...
if( $_POST['password'] !== $_POST['vpassword'] ) {
$return_info["errors"][] = "Passwords didn't match.";
}
// if account IS created, just flip the created switch
// ...
$try_inserting = $stmt->execute();
if( $try_inserting ) { # replace this with an actual error check
$return_info["created"] = true;
}
// now everything comes back: creation status, warnings, errors, etc...
return( $return_info );
}
This function refactoring standardizes all of its returns, so that it's predictable in dealing with it. You can do simple statements like:
$attempt = add_member();
if( $attempt["created"] === true ) {
echo "added member!";
}
Whatever is calling this can also do very simple checks for errors, warnings, notices:
if( !empty($attempt["errors"]) ) {
// display the errors
}

Related

Pass a $_POST value into a function parameter with a PDO variable

I have setup a pdo connection and pass that as a variable into a function. This all works fine and the function returns correctly. If I run the function in a conditional statement with the PDO variable and a name it runs correctly - if name is in database it echos correctly if not then it also echos correctly. What I want to do is to pass the value of a form post to the function so that it checks to see if it exists in the database. Here is my code:
The function checks to see if the column count is one.
function user_exists($pdo, $username) {
$stmt = $pdo->prepare('SELECT COUNT(uid) FROM users WHERE username = :username');
$stmt->execute(['username' => $username]);
$result = $stmt->fetchColumn();
return ($result == 1);
}
If the admin user exists in the database echo 'exists' - Just for testing.
if(user_exists($pdo,'admin') == true) {
echo "exists";
} else {
echo "doesnt exist";
}
Checks to see of both fields have been entered then I want it to check if the username entered is in the database, but I am doing something wrong.
if(!empty($_POST) === true) {
$username = $_POST['username'];
$pwood = $_POST['password'];
if(empty($username) === true || empty($pwood) === true) {
echo "You need to enter a username and password";
} else if (user_exists($pdo,$_POST['username']) == false){
echo 'We can\'t find that username. Please try again or register';
}
}
Better don't compare with bool values, just use
//...see below
require_once('UserRepository.php');
$ur = new UserRepostory($pdo);
if(!empty($_POST)) {
if (empty($username) || empty($pwood)) {
// something
} else if (!$ur->exists($_POST['username'])) { // your user_exists($pdo, $username) works fine, too
// something else
}
}
Especially the initial if(!empty($_POST) === true) { is hard to read and lead to errors 'cause of misunderstood operator priority.
Update based on the comments above, here is an example with a class:
// UserRepository.php
class UserRepository {
private $pdo;
// '\PDO' instead of 'PDO', see PHP Namespacing
public function __construct (\PDO $pdo)
{
$this->pdo = $pdo;
}
public function exists($username)
{
$sql = 'SELECT COUNT(uid) FROM users WHERE username = :username');
$stmt = $this->pdo->prepare($sql);
$stmt->execute(['username' => $username]);
$result = $stmt->fetchColumn();
return (bool) $result;
}
}

Get int from column by using email to identify row

I want to get and echo a users permission level.
I have a function where the users email is passed, the function then needs to get the users permission level and return it, so it can be echoed on another page.
I imagine the function will look though the database for the passed email, it then finds the users permission and returns with that.
In the 'User.class.php'
public static function permGetter($email)
{
try
{
$db = Database::getInstance();
$stmt = $db->prepare('SELECT permission FROM users WHERE email = :email LIMIT 1');
$stmt->execute([':permission'=>$permission]);
$user = $stmt->fetchObject('User');
if($user !== false)
{
return $permission;
}
}
catch (PDOException $exception)
{
error_log($exception->getMessage());
return false;
}
}
In the 'permRequest.php'
<?php
ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
error_reporting(E_ALL);
require_once("../includes/init.php");
//Get passed from an external program
$email = $_GET['email'];
$pass = $_GET['pass'];
if($email && $pass !== null)
{
// Checks if the user's entered credential matches with those in database
if(Auth::getInstance()->login($email, $pass))
{
//Uses the passed email to get permission level in 'User.class.php'
if(User::permGetter($email))
{
echo 'Permission ' + (int) $permission;
}
}
else
{
//I use level 5 as a debug so i can see when it fails
echo 'Permission 5';
}
}
?>
Database
Here's an example on what my database looks like.
Edit 1
Okay messing about, I think i got closer to the solution.
First, #Lawrence Cherone, thanks for pointing out my mistake in my execute.
Okay I have changed my code in
User.class.php
public static function permGetter($email, $permission)
{
try
{
$db = Database::getInstance();
$stmt = $db->prepare('SELECT permission FROM users WHERE email = :email');
$stmt->execute([':email'=>$email]);
$row = $stmt->fetch(PDO::FETCH_NUM);
$permission = $row['permission'];
}
catch (PDOException $exception)
{
error_log($exception->getMessage());
return false;
}
}
I have made small changes to
permRequest.php
<?php
ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
error_reporting(E_ALL);
require_once("../includes/init.php");
//Get passed from an external program
$email = $_GET['email'];
$pass = $_GET['pass'];
$permission = '';
if($email && $pass !== null)
{
// Checks if the user's entered credential matches with those in database
if(Auth::getInstance()->login($email, $pass))
{
//Uses the passed email to get permission level in 'User.class.php'
if(User::permGetter($email, $permission))
{
echo 'Permission ', $permission;
}
}
}
?>
But now i get an error. The error is this Notice: Undefined index: permission in /classes/User.class.php on line 56
So, I read up on it and it seemed like it should be emptied first, so I empty it in permRequest.php that's why I'm passing it too, but I still get this error after i emptied it?
However if i change
$row = $stmt->fetch(PDO::FETCH_NUM);
to
$row = $stmt->fetch(PDO::FETCH_ASSOC);
/* OR */
$row = $stmt->fetch(PDO::FETCH_BOTH);
I get no error but it simply says my email or password is incorrect, which it isn't I have double and triple checked it.
So I'm confused to which PDO::FETCH_ I should use. I have read this (Click here) and I would say that both ASSOC, BOTH and NUM would fit the purpose.
So why is one giving an error while the two other's simply fails the login?
Edit 2
Found the solution and i have written it as a Answer. Can't accept it for the next two days however.
I moved everything out of the User.class.php and moved it into permRequest.php. This solved my problem for some reason. So my code looks like this now
<?php
ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
error_reporting(E_ALL ^ E_NOTICE);
require_once("../includes/init.php");
$email = $_GET['email'];
$pass = $_GET['pass'];
if($email && $pass !== null)
{
if(Auth::getInstance()->login($email, $pass))
{
try
{
$db = Database::getInstance();
$stmt = $db->prepare("SELECT * FROM users WHERE email = :email");
$stmt->execute([':email' => $email]);
$row = $stmt->fetch(PDO::FETCH_ASSOC);
$sub = $row['permission'];
echo 'Permission ', $sub;
}
catch (PDOException $exception)
{
error_log($exception->getMessage());
return false;
}
}
}
And I don't use the User.class.php for this function.
So my guess is something went wrong when returning $sub when it was in User.class.php

What Can I Do Instead Of Multiple If Statements? PHP Register Script

As you can see in the script below, I use multiple if statements when checking registration inputs. Is there an easier, less spaghetti?
The script works as is, but i would like it to be neater.
<?php
if (isset($_POST['register'])) {
$uname = trim($_POST['uName']);
$email = trim($_POST['email']);
$pass = trim($_POST['pass']);
$passCon = trim($_POST['passCon']);
$uname = strip_tags($uname);
$email = strip_tags($email);
$pass = strip_tags($pass);
$passCon = strip_tags($passCon);
if (!empty($pass)) {
if (!empty($email)) {
if (!empty($uname)) {
if ($pass == $passCon) {
$query = "SELECT username FROM users WHERE username='$uname'";
$result = mysqli_query($conn, $query);
$checkUsername = mysqli_num_rows($result);
if ($checkUsername == 0) {
$query = "SELECT email FROM users WHERE email='$email'";
$result = mysqli_query($conn, $query);
$count = mysqli_num_rows($result);
if ($count == 0) {
$password = hash('sha256', $pass);
$queryInsert = "INSERT INTO users(id, username, email, password, date) VALUES('', '$uname', '$email', '$password', '" . time() . "')";
$res = mysqli_query($conn, $queryInsert);
if ($res) {
$errTyp = "success";
$errMsg = "successfully registered, you may login now";
}
} else {
$errTyp = "warning";
$errMsg = "Sorry Email already in use";
}
} else {
$errTyp = "warning";
$errMsg = "Sorry Username already in use";
}
} else {
$errTyp = "warning";
$errMsg = "Passwords didn't match";
}
} else {
$errTyp = "warning";
$errMsg = "You didn't enter a Username";
}
} else {
$errTyp = "warning";
$errMsg = "You didn't enter an email address";
}
} else {
$errTyp = "warning";
$errMsg = "You didn't enter a password";
}
}
Thank you,
Jay
The problem you are facing is not at all uncommon. Many programmers have faced this issue. Let me help you along the way restructuring your script.
First of all, let's get rid of the nested if-else statements. They confuse and obfuscate what is really going on.
Version 1:
if (!isset($_POST['register']))
redirect('register.php'); // Let's assume that redirect() redirects the user to a different web page and exit()s the script.
$uname = $_POST['uName'];
$email = $_POST['email'];
$pass = $_POST['pass'];
$passRepeat = $_POST['passRepeat'];
if (empty($pass)) {
$errorMessage = "You didn't enter a password";
}
if (empty($email)) {
$errorMessage = "You didn't enter an email address";
}
if (empty($uname)) {
$errorMessage = "You didn't enter a Username";
}
if ($pass !== $passRepeat) {
$errMsg = "Passwords didn't match";
}
$query = "SELECT username FROM users WHERE username='$uname'";
$result = mysqli_query($conn, $query);
$checkUsername = mysqli_num_rows($result);
if ($checkUsername !== 0) {
$errMsg = 'Sorry Username already in use';
}
$query = "SELECT email FROM users WHERE email='$email'";
$result = mysqli_query($conn, $query);
$count = mysqli_num_rows($result);
if ($count !== 0) {
$errMsg = 'Sorry Email already in use';
}
$password = hash('sha256', $pass);
$queryInsert = "INSERT INTO users(id, username, email, password, date) VALUES('', '$uname', '$email', '$password', '" . time() . "')";
$res = mysqli_query($conn, $queryInsert);
Note that although this avoids the nested if statements, this is not the same as the original code, because the errors will fall through. Let's fix that. While we are at it, why would we want to return after the first error occurs? Let's return all the errors at once!
Version 2:
$errors = array();
if (empty($pass)) {
$errors[] = "You didn't enter a password";
}
if (empty($email)) {
$errors[] = "You didn't enter an email address";
}
if (empty($uname)) {
$errors[] = "You didn't enter a username";
}
if ($pass !== $passRepeat) {
$errors[] = "Passwords didn't match";
}
$query = "SELECT username FROM users WHERE username='$uname'";
$result = mysqli_query($conn, $query);
$usernameExists = mysqli_num_rows($result) > 0;
if ($usernameExists) {
$errors[] = 'Sorry Username already in use';
}
$query = "SELECT email FROM users WHERE email='$email'";
$result = mysqli_query($conn, $query);
$emailExists = mysqli_num_rows($result) > 0;
if ($emailExists) {
$errors[] = 'Sorry Email already in use';
}
if (count($errors) === 0) {
$password = hash('sha256', $pass);
$queryInsert = "INSERT INTO users(id, username, email, password, date) VALUES('', '$uname', '$email', '$password', '" . time() . "')";
$res = mysqli_query($conn, $queryInsert);
redirect('register_success.php');
} else {
render_errors($errors);
}
Pretty clean so far! Note that we could replace the if (empty($var)) statements with a for-loop. However, I think that is overkill in this situation.
As a side note, please remember that this code is vulnerable to SQL injection. Fixing that issue is beyond the scope of the question.
Less spaghetti? Start with functional decomposition, then work towards separating the task of sanitation from that of validation. I will leave out many steps that I take (such as verifying the form / $_POST / filter_input_array() has the correct number of inputs, and the correct keys are in the $_POST superglobal / INPUT_POST, etc, you might want to think about that.). Alter some of my techniques for your exact needs. Your program should be less spaghetti afterwards. :-)
Sanitize then validate. You have to keep them separated, so to speak. ;-)
Sanitizing with Functional Decomposition
Make a single task its own block of code.
If all of your sanitization steps (trim(), strip_tags(), etc.) are the same for all of your form fields, then make a sanitizer function to do that work. Note, that the one-time way you are trimming and stripping tags can be improved upon simply by using a loop. Save the original value in a variable, then trim(), strip_tags(), etc within a while loop. Compare the results to the original. If they are the same, break. If they differ, save the current value of the form field in your variable again and let the loop run again.
function sanitize($formValue)
{
$oldValue = $formValue;
do
{
$formValue = trim($formValue);
$formValue = strip_tags($formValue);
//Anything else you want to do.
$formValue = trim($formValue);
if($formValue === $oldValue)
{
break;
}
$oldValue = $formValue;
}
while(1); //Infinite loop
return $formValue;
}
Then, simply run this function in a loop.
$sanitized = [];
foreach($_POST as $key => $value)
{
$sanitized[$key] = sanitize($value);
}
/* You can keep track your variable anyway you want.*/
Looking further down the road, it is times like this where devising an input source ($_POST, $_GET, $_SESSION, $_FILES, $_COOKIE, etc..) based sanitizing, class hierarcy really comes in handy. Moreover, basing that class hierarchy on the use of filter_input_array() really puts you a head of the game. What about validation?
Validating with Functional Decomposition
You could look at each form field as needing its own validating function. Then, only the logic required to check one form field will be contained within the block. The key, retain your Boolean logic by having the validator functions return the results of a test (true / false).
function uname($uname, &$error)
{
if(! /* Some test */)
{
$error = 'Totally wrong!'
}
elseif(! /* Another test */)
{
$error = 'Incredibly wrong!'
}
else
{
$error = NULL;
}
return !isset($error) //If error is set, then the test has failed.
}
function email($email, &$error)
{
if(! /* Some test */)
{
$error = 'Totally wrong!'
}
elseif(! /* Another test */)
{
$error = 'Incredibly wrong!'
}
else
{
$error = NULL;
}
return !isset($error) //If error is set, then the test has failed.
}
function pass($pass, &$error)
{
if(! /* Some test */)
{
$error = 'Totally wrong!'
}
elseif(! /* Another test */)
{
$error = 'Incredibly wrong!'
}
else
{
$error = NULL;
}
return !isset($error) //If error is set, then the test has failed.
}
function passCon($passCon, &$error)
{
if(! /* Some test */)
{
$error = 'Totally wrong!'
}
elseif(! /* Another test */)
{
$error = 'Incredibly wrong!'
}
else
{
$error = NULL;
}
return !isset($error) //If error is set, then the test has failed.
}
In PHP, you can use variable functions to name your function the same as the fields they are checking. So, to execute these validators, simply do this.
$errorMsgs = [];
foreach($sanitized as $key => $value)
{
$key($value, $errorMsgs[$key])
}
Then, generally speaking, you just need to see if there are any errors in the $errorMsgs array. Do this by processing the $errorMsgs array
$error = false;
foreach($errorMsgs as $key => $value)
{
if(isset($value))
{
//There is an error in the $key field
$error = true;
}
}
..and then.
if($error === true)
{
//Prompt user in some way and terminate processing.
}
// Send email, login, etc ....
Taken further, you could create a generic, Validator, super class.
All this being said. I do all of my sanitization and validation in an object oriented way to reduce code duplication. The Sanitizer super class has children (PostSanitizer, GetSanitizer, ....). The Validator super class has all the test one might perform on a string, integer, or float. Children of the Validator superclass are page/form specific. But, when something like a form token is needed, it's validating method is found in the Validator super-class because it can be used on any form.
A good validation routine keeps track of:
1) Input values in an associative array..
2) Test results (Booleans) in an associative array. Test results (true/false) can be converted to CSS classes or a JSON string of '1's and '0's.
3) Error messages in an associative array.
..then makes final decisions about what to do with the input values and/or error messages based on the test results (by key). If there are errors (false values in the a hypothetical test results array), use the error messages that have the corresponding key.
My previous example condenses the final error checking and error message data structures with one array, but using separate data structures allows more flexibility (decouples error messages from the detected errors). Simply store the results of each validating variable function into a $testResults array like this.
function sanitize($formValue)
{
$oldValue = $formValue;
do
{
$formValue = trim($formValue);
$formValue = strip_tags($formValue);
//Anything else you want to do.
$formValue = trim($formValue);
if($formValue === $oldValue)
{
break;
}
$oldValue = $formValue;
}
while(1); //Infinite loop
return $formValue;
}
$sanitized = [];
foreach($_POST as $key => $value)
{
$sanitized[$key] = sanitize($value);
}
$testResults = [];
$errorMsgs = [];
foreach($sanitized as $key => $value)
{
$testResults[$key] = $key($value, $errorMsgs[$key])
}
if(!in_array(false, $testResults, true))
{
return true //Assuming that, ultimately, you need to know if everything worked or not, and will take action on this elsewhere. It's up to you to make the correct functions/methods, but this general foundation can get you going.
}
return false; //Obviously. Do not submit the form. Show the errors (CSS and error messages).
Then, simply check for the existence of false in the $testResults array. Get the corresponding error message from $errorMsgs using the appropriate $key. Using this generic, final stub, you can create a powerful santization and validation routine, especially if you go object oriented.
Eventually, you will begin to see that the same kinds of test are being repeated among the various validation variable functions: data type, length, regular expression, exact matches, must be a value within a set, etc. Thus, the primary difference between the validating variable functions will be the minimum and maximum string lengths, regex patterns, etc... If you are savvy, you can create an associative array that is used to "program" each variable function with its set of validation parameters. That's getting a bit beyond the scope, but that is what I do.
Thus, all my variable functions perform the same basic tests via factored out logic using a method of class Validator called validateInput(). This method receives the following arguments
1) The value to be tested.
2) An associative array of the test parameters (which can specify datatype)
3) An array element, passed in as a variable (by reference), that corresponds the field being tested that will hold the error message, if any.
What's funny, is that I use a two step sanitization and a two step validation. I use a custom filter algorithm using PHP functions, then I use the PECL filter functions (filter_input_array()). If anything fails during these steps, I throw a SecurityException (because I extend RuntimeException).
Only after these filters pass do I attempt to use the PHP/PECL filter valiation functions. Then, I run my own validation routine using validating, variable functions. Yes, these only run if the previous test passed as true (to avoid overwriting previous failures and corresponding error message).
This is entirely object oriented.
Hope I helped.

Update from URL

I have been working towards updating a password after a request has been sent and collected from email, the request part seems to work but when I try to update the password nothing seems to happen, my password length is set at 255, initially I checked if it was the correct id I was getting and it seems to be, when I manually run the query in easyphp adding what I want updated it seems to work, I have looked at my network response no errors are showing and checked my error logs nothing there either. Any advice would be great.
<?php
require_once'connection.php';
$userInput = new UserInput();
$userInput->trimInput();
$id = '';
if( isset( $_GET['reset'])) {
$id = $_GET['reset'];
}
header('Content-Type: application/json');
$errors = [];
if (empty($_SESSION['resetPassword'])) {
$_SESSION['resetPassword'] = 1;
}
else {
$_SESSION['resetPassword']++;
}
if($_SESSION['resetPassword'] > 3){
$errors[]= ["name"=>"username","error"=>"Too many attempts try again in 15 minutes"];
if(!isset($_SESSION["timeoutPassword"])){
$_SESSION['timeoutPassword'] = time();
};
$st = $_SESSION['timeoutPassword'] + 900;
if(time() > $st){
unset($_SESSION['resetPassword']);
unset($_SESSION['timeoutPassword']);
}
}
else {
if(filter_var($_GET['password'], FILTER_VALIDATE_REGEXP,["options"=> [ "regexp" => "/.{6,25}/"]]) === FALSE){
$errors[]= ["name"=>"password","error"=>"invalid password (6 to 25 characters)"];
}
if(!preg_match("/(?=[a-z]*[0-9])(?=[0-9]*[a-z])([a-z0-9-]+)/i",$_GET['password'])) {
$errors[]= ["name"=>"password","error"=>"Password must contain numbers and letters"];
}
if($_GET['password'] !== $_GET['repeatPassword']){
$errors[]= ["name"=>"repeatPassword","error"=>"passwords don't match"];
}
if (count($errors) === 0) {
try{
$sql = "UPDATE username SET activecode = 'Active', password = :password WHERE activecode = :reset";
$stmt = $db->prepare($sql);
$stmt->bindValue(':password', password_hash($_GET['password'], PASSWORD_DEFAULT));
$stmt->bindValue(':reset', $id);
$stmt->execute();
$stmt->rowCount();
if ( $stmt->rowCount() === 1){
echo json_encode(["success"=>"Your password has been reset"]);
exit(0);
}
}
catch(Exception $e ) {
$errors[]= ["name"=>"username","error"=>"Unable to update password"];
}
}
}
echo json_encode(["errors"=>$errors]);

Validating user input using php

I'm new to php and mysql and I'm trying to check if a user has entered something into a a coupls of textboxes and to also check if what has been entered is string. I want to do a check before posting to the database. I also want the html form to retain the value initially entered by the user. Please how do i achieve this.
Here's what I've done so far. This works but it still shows that the data has been entered successfully.
if(isset($_POST['register'])){
//PHP FIELD VALIDATIONS
if($_POST['fname']==""){
echo "First name is required <br/>";
}
else{
$fname= filter_var($_POST['fname'], FILTER_SANITIZE_STRING);
}
if($_POST['lname']==""){
echo "Last name is required <br/>";
}
else{
$lname= $_POST['lname'];
}
if($_POST['email']==""){
echo "Email address is required <br/>";
}
else{
$email= $_POST['email'];
}
if($_POST['pword']==""){
echo "Password is required<br/>";
}
else{
$pword= $_POST['pword'];
}
$fname=mysql_real_escape_string($fname);
$lname=mysql_real_escape_string($lname);
$email=mysql_real_escape_string($email);
$pword=mysql_real_escape_string($pword);
require_once 'scripts/connect_to_mysql.php';
$sql = "INSERT INTO customer ".
"(First_name,Last_name, Email, Password, date_added) ".
"VALUES('$fname','$lname','$email','$pword', NOW())";
//echo $sql;
mysql_select_db('online_store');
$result = mysql_query( $sql, $conn );
if(! $result )
{
die('Could not enter data: ' . mysql_error());
}
echo "<span style='color:green;'>Entered data successfully</span>";
mysql_close($conn);
}
?>
Firstly and most importantly, you should change from mysql to either mysqli or PDO.
Secondly, to ensure all fields are entered before submitting, you could loop through the inputs, checking each if they are empty, and running any input specific checks you wish. i.e checking if an input is a string you can do is_string($variable).
If any of the checks fail, set a variable e.g. $failedValidation, then wrap your sql execution code in an if statement - if $failedValidation !isset, or is set to false, however you want to handle it - then run the code.
Instead of using $fname=mysql_real_escape_string($fname); use $fname = htmlspecialchars($fname);.
Looping through $_POST array:
$Validated = True; // Validated needs to be set to true, for the SQL code to run
// Loop through all variables stored in the $_POST array
foreach($_POST as $value)
{
if(empty($value)) // If any of the $_POST variables are empty, set $Validated to false
{
$Validated = False;
}
}
// If none of the fields were empty, $Validated will have remained true after our loop
if($Validated == True) {
// Run SQL code
}
Hopefully I've explained it in a way you can understand, and I hope it helps you.
Form Validation:
You'll need a mechanism that validates fields in your form and echos some validation error. The way you write php is pretty outdated, today php application usually use a pattern like MVC for the separation of concerns. Read about both, MVC and SoC.
However, the most simple solution here would be a validation class:
class Validator {
public static function email($postField, $message) {
if (isset($_POST[$postField]) {
// Example of full email validation here https://github.com/cakephp/cakephp/blob/master/lib/Cake/Utility/Validation.php#L437
$regex = '...';
if (!preg_match($regex, $email)) {
return $message;
}
}
}
public static function notEmpty($postField, $message) {
if (isset($_POST[$postField]) && empty($_POST[$postField])) {
return $message;
}
}
public static function multi($field, $rules = array()) {
foreach ($rules as $rule => $message) {
echo Validator::{$rule}($field, $message);
}
}
}
echo Validator::email('email', 'Your email address is wrong!');
Validator::multi('email', array('email' => '...', 'notEmpty' => '...'));
This is a very basic example but you get the idea. This could be extended and improved a lot to automate it much more.
Honestly I'm not in the mood to write a complete article about that right now because I guess there are plenty of them already, just try to Google for server side form validation in the context of php.
Database:
You're using the as deprecated flagged mysql_* functions, don't use them, use mysqli or PDO instead.
There is a big warning for these functions on each documentation page:
This extension is deprecated as of PHP 5.5.0, and will be removed in
the future. Instead, the MySQLi or PDO_MySQL extension should be used.
See also MySQL: choosing an API guide and related FAQ for more
information.
For how you properly use and escape SQL queries see this: How can I prevent SQL injection in PHP?
PDO example.
$stmt = $pdo->prepare('SELECT * FROM employees WHERE name = :name');
$stmt->execute(array('name' => $name));
foreach ($stmt as $row) {
// do something with $row
}
Use below code:
if(isset($_POST['register'])){
//PHP FIELD VALIDATIONS
$validated = true;
if($_POST['fname']==""){
echo "First name is required <br/>";
$validated = false;
}
else{
$fname= filter_var($_POST['fname'], FILTER_SANITIZE_STRING);
}
if($_POST['lname']==""){
echo "Last name is required <br/>";
$validated = false;
}
else{
$lname= $_POST['lname'];
}
if($_POST['email']==""){
echo "Email address is required <br/>";
$validated = false;
}
else{
$email= $_POST['email'];
}
if($_POST['pword']==""){
echo "Password is required<br/>";
$validated = false;
}
else{
$pword= $_POST['pword'];
}
if ($validated) {
$fname=mysql_real_escape_string($fname);
$lname=mysql_real_escape_string($lname);
$email=mysql_real_escape_string($email);
$pword=mysql_real_escape_string($pword);
require_once 'scripts/connect_to_mysql.php';
$sql = "INSERT INTO customer ".
"(First_name,Last_name, Email, Password, date_added) ".
"VALUES('$fname','$lname','$email','$pword', NOW())";
//echo $sql;
mysql_select_db('online_store');
$result = mysql_query( $sql, $conn );
if(! $result )
{
die('Could not enter data: ' . mysql_error());
}
echo "<span style='color:green;'>Entered data successfully</span>";
mysql_close($conn);
}
}

Categories