Best Practice for PHP exit() - php

I am working on a PHP project and I have a file called login.php. This file contains a HTML code that basically consists of a form that has 2 inputs (used for email and password) and a submit button. Before the HTML there is a PHP script that checks if the inputs are valid (not empty, the user exists in the db). I use an hidden input field (called formsubmitted) to check if the user has pressed the submit button. If the values are valid then the PHP script redirects the user to the home page, if not, the PHP script prints a HTML div in which I store the error message and then the HTML for the form.
I would like to print only the error div, not the rest of the HTML, and for this I could use the exit() function. Now I don't know if this is a good practice, I have searched the web but didn't find any useful. I would appreciate if someone could tell me if it is ok to do so.
Thanks!
Here is how my code looks briefly:
<?php
if (isset($_POST['formsubmitted'])) {
//check if the email and password are valid
if (valid) {
header("Location:home.php");
} else {
echo "<div id='error-section'>";
echo "message";
echo "</div>"
}
}
exit();
?>
<!DOCTYPE html>
<html>
...............
</html>

To answer your question: I personally wouldn't use exit() statements anywhere in your code (unless it's after a REST API echo(json_encode(array()) echo statement.) It just can cause a lot of head aches down the road with debugging errors.
(It also can break \ob_*()\ calls as well as the majority of framework's display modules - because the framework won't be able to get to it's echo statements.)
My Practice:
I always have a .errors div in my forms:
<?php if (isset($errors) && !empty($errors): ?>
<?php foreach ($errors as $error): ?>
<div class="alert alert-danger" role="alert">
<strong>Error: </strong> <?php echo $error['message'] ?>
</div>
<?php endforeach; ?>
<?php endif; ?>
<form>
<!--- form here -->
</form>
This way you just pass the $errors array into your form and everything works honkey dory and you can avoid using exit() - using exit() has it's time and place, but because it doesn't give you a message or log anything it can be a royal pain to debug later on.
As a closing note, this method allows you to pass an array to the errors like so:
array(
'first_name' => 'First Name Required',
'last_name' => 'Last Name Required',
'zip_code' => 'Must enter a valid zip code'
)
Which allows you to, when you're rendering your form add an .error class to your input fields which will help your users locate which input had the problem - always nice:
<input id="first_name" type="text" class="my_input_class<?php (isset($errors) && isset($errors['first_name'])) ? ' error' : '' ?>">

try this :(UPDATED)
<?php
if (isset($_POST['formsubmitted'])) {
//check if the email and password are valid
if (valid) {
header("Location:home.php");
} else {
die("<html>
<head>
<!-- ADD STUFF HERE IF YOU WANT-->
</head>
<body>
<div id='error-section'>message</div>
</body>
</html>");
//you can use exit if you want too
}
}
?>
<!DOCTYPE html>
<html>
...............
</html>

The best practice is to show the form with an error message so the user has opportunity to try again. Not valid credentials can have several meaning. In any case you shouldn't just show error message and dead end for the user. Provide a meaningful error message with opportunity to try again.

Related

How to display error messages on redirect?

It's worth noting I'm new to php. I would like to have an answer in php as well (if possible).
Here's what I'm trying to achieve: I want to redirect the user if any errors I check for are found to a html/php form (that the user see's first where inputs are previously created) with custom error messages that come from a file separate to the html/php form.
Details: The User see's the HTML/PHP form first where they enter names in a csv format. After they click create, the names are processed in another file of just php where the names are checked for errors and other such things. If an error is found I want the User to be redirected to the HTML/PHP form where they can fix the errors and whatever corresponding error messages are displayed. Once they fix the names the User can click the 'create user' button and processed again (without errors hopefully) and upon completion, redirect user to a page where names and such things are displayed. The redirect happens after the headers are sent. From what I've read this isn't the best thing but, for now, it'll do for me.
Code For HTML/PHP form:
<!DOCTYPE HTML>
<HTML>
<head>
<title>PHP FORM</title>
</head>
<body>
<form method="post" action="processForm.php">
Name: <input type="text" name="names" required = "required"><br>
<input type="submit" value="Create Users" onclick="formInputNames"><br>
Activate: <input type="checkbox" name="activate">
</form>
<?php
// include 'processForm.php';
// errorCheck($fullname,$nameSplit,$formInputNames);
?>
</body>
</html>
I tried messing around with 'include' but it doesn't seem to do anything, however, I kept it here to help illustrate what I'm trying to achieve.
Code For Process:
$formInputNames = $_POST['names'];
$active = (isset($_POST['activate'])) ? $_POST['activate'] : false;
//checks if activate checkbox is being used
$email = '#grabby.com';
echo "<br>";
echo "<br>";
$fullnames = explode(", ", $_POST['names']);
if ($active == true) {
$active = '1';
//sets activate checkbox to '1' if it has been selected
}
/*----------------------Function to Insert User---------------------------*/
A Function is here to place names and other fields in database.
/*-------------------------End Function to Insert User--------------------*/
/*-----------------------Function for Errors---------------------*/
function errorCheck($fullname,$nameSplit,$formInputNames){
if ($formInputNames == empty($fullname)){
echo 'Error: Name Missing Here: '.$fullname.'<br><br>';
redirect('form.php');
}
elseif ($formInputNames == empty($nameSplit[0])) {
echo 'Error: First Name Missing in: '.$fullname.'<br><br>';
redirect('form.php');
}
elseif ($formInputNames == empty($nameSplit[1])) {
echo 'Error: Last Name Missing in: '.$fullname.'<br><br>';
redirect('form.php');
}
elseif (preg_match('/[^A-Za-z, ]/', $fullname)) {
echo 'Error: Found Illegal Character in: '.$fullname.'<br><br>';
redirect('form.php');
}
}
/*-----------------------------End Function for Errors------------------------*/
/*--------------------------Function for Redirect-------------------------*/
function redirect($url){
$string = '<script type="text/javascript">';
$string .= 'window.location = "' .$url. '"';
$string .= '</script>';
echo $string;
}
/*-------------------------End Function for Redirect-----------------------*/
// Connect to database
I connect to the database here
foreach ($fullnames as $fullname) {
$nameSplit = explode(" ", $fullname);
//opens the database
I Open the database here
errorCheck($fullname,$nameSplit,$formInputNames);
$firstName = $nameSplit[0];//sets first part of name to first name
$lastName = $nameSplit[1];//sets second part of name to last name
$emailUser = $nameSplit[0].$email;//sets first part and adds email extension
newUser($firstName,$lastName,$emailUser,$active,$conn);
redirect('viewAll.php');
//echo '<META HTTP-EQUIV="Refresh" Content="0; URL=viewAll.php">';
//if you try this code out, you can see my redirect to viewAll doesn't work when errors are found...I would appreciate help fixing this as well. My immediate fix is using the line under it but I don't like it.
}
All the research I've done hasn't gotten me far. I understand that sending the headers isn't good practice. I looked at ob_open (php function-I think it was called) and couldn't figure out how to properly use it. I couldn't find a question on here that satisfied the conditions I'm trying to meet either.
Any help is certainly appreciated.Thank You
EDIT: This is not a duplicate of 'Passing error messages in PHP'.
-------While the idea is similar, they are 'Passing error messages in PHP' before the headers are sent. Therefore it's not the same.
Store the error in a session and echo it on the destination page.
Put session_start() at the top of the code of the form.php page. Like this:
<?php session_start(); ?>
<!DOCTYPE HTML>
<HTML>
<head>
Then replace the echo error with:
$_SESSION['error'] = 'Error: Name Missing Here: '.$fullname.'<br><br>';
redirect('form.php');
Use this in your conditions instead of the echo. Then in the form.php page:
if (isset($_SESSION['error'])) {
echo $_SESSION['error'];
unset($_SESSION['error']);
}
The unset makes sure that the error is repeated.
An HTTP Redirect causes a new HTTP request. Since php is stateless, it cannot natively support remembering a message to display to a specific user in another request. In order to get around this limitation, you would need to use a stateful storage mechanism (session or cookies), or pass the error message along to the next request via query string parameter. The usual way this is handled is by using session storage to save flash messages.
Here is a library that can make it a bit easier for you https://github.com/plasticbrain/PhpFlashMessages
Set session of error and display on the page on which you are redirecting

Display alert box upon form submission

So I have these two pages: pageOne.php and pageTwo.php.The form is in pageOne.php:
<form method="post" action="pageTwo.php"> .... </form>
and doing all the data collection-validation-insertion and sending out mails in pageTwo.php (the reason i'm doing everything in two separate pages is to avoid the data re-submission upon page refresh...this was the easiest way for me to handle the issue). So far everything is working perfectly.
Now, I want to display a success/failure message using alert box after the form submission and tried few things w/o any luck. E.g. when I tried THIS solution on pageTwo.php, no pop up box shows up and I think that's because I have this header on top of that page
<?php header("Location: http://TestPages.com/pageOne.php"); ?>
<?php
if( $_POST ) {
//collect the data
//insert the data into DB
//send out the mails IFF the data insertion works
echo "<script type='text/javascript'>alert('It worked!')</script>";
}else
echo "<script type='text/javascript'>alert('Did NOT work')</script>";
?>
And when tried this second solution in pageOne.php, I get the alert box popping up every time i refresh the page and get the failure message even though the data had been inserted into database and mails were sent out. pageOne.php:
<html>
<body>
<?php
if( $GLOBALS["posted"]) //if($posted)
echo "<script type='text/javascript'>alert('It worked!')</script>";
else
echo "<script type='text/javascript'>alert('Did NOT work')</script>";
?>
<form method="post" action="pageTwo.php"> .... </form>
</body>
and in pageTwo.php:
<?php header("Location: http://TestPages.com/pageOne.php"); ?>
<?php
$posted = false;
if( $_POST ) {
$posted = true;
//collect the data
//insert the data into DB
//send out the mails IFF the data insertion works
} ?>
Why isn't this simple thing working :( ? is there any easy way to fix it? Thank you!!
UPDATE
So I have made some changes according to drrcknlsn's sugession and this is what I have so far....pageOne.php:
<?php
session_start();
if (isset($_SESSION['posted']) && $_SESSION['posted']) {
unset($_SESSION['posted']);
// the form was posted - do something here
echo "<script type='text/javascript'>alert('It worked!')</script>";
} else
echo "<script type='text/javascript'>alert('Did NOT work')</script>";
?>
<html> <body>
<form method="post" action="pageTwo.php"> .... </form>
</body> </html>
and pageTwo.php:
<?php
session_start();
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$_SESSION['posted'] = true;
//collect the data
//insert the data into DB
//send out the mails IFF the data insertion works
header('Location: http://TestPages.com/pageOne.php');
exit;
} ?>
With these changes now the page's redirection and success message is working, but i get the failure msg every time i open/refresh the page (i know that's because the session key is not set yet)...how can i avoid that? Thanks again!!
First, a couple points:
Variables (even globals) are not shared across requests like you're trying to do in your bottom example. In order for $posted to be accessible in both pages, you must persist it in some way. Usually this involves setting a session variable (e.g. $_SESSION['posted'] = true;), but it could also be persisted in a cookie, in a database, on the filesystem, in a cache, etc.
Use something like if ($_SERVER['REQUEST_METHOD'] === 'POST') instead of if ($_POST). While the latter is probably safe in most cases, it's better to get in the habit of using the former because there exists an edge case where $_POST can be empty with a valid POST request, and it may be a hard bug to track down.
One potential pattern to solve your problem using the above advice:
pageOne.php:
<?php
session_start();
if (isset($_SESSION['posted']) && $_SESSION['posted']) {
unset($_SESSION['posted']);
// the form was posted - do something here
}
?>
...
<form>...</form>
pageTwo.php:
<?php
session_start();
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$_SESSION['posted'] = true;
// do form processing stuff here
header('Location: pageOne.php');
exit;
}
// show an error page here (users shouldn't ever see it, unless they're snooping around)
It looks like it's a scope problem.
use:
global $posted = true;
http://php.net/manual/en/language.variables.scope.php

use php to change a html elements inner text

I have a basic form, which i need to put some validation into, I have a span area and I want on pressing of the submit button, for a predefined message to show in that box if a field is empty.
Something like
if ($mytextfield = null) {
//My custom error text to appear in the spcificed #logggingerror field
}
I know i can do this with jquery (document.getElementbyId('#errorlogging').innerHTML = "Text Here"), but how can I do this with PHP?
Bit of a new thing for me with php, any help greatly appreciated :)
Thanks
You could do it it a couple of ways. You can create a $error variable. Make it so that the $error is always created (even if everything checks out OK) but it needs to be empty if there is no error, or else the value must be the error.
Do it like this:
<?php
if(isset($_POST['submit'])){
if(empty($_POST['somevar'])){
$error = "Somevar was empty!";
}
}
?>
<h2>FORM</h2>
<form method="post">
<input type="text" name="somevar" />
<?php
if(isset($error) && !empty($error)){
?>
<span class="error"><?= $error; ?></span>
<?php
}
?>
</form>
If you want change it dynamically in client-side, there is no way but ajax. PHP works at server-side and you have to use post/get requests.
Form fields sent to php in a $_REQUEST, $_GET or $_POST variables...
For validate the field param you may write like this:
if(strlen($_REQUEST['username']) < 6){
echo 'false';
}
else{
echo 'true';
}
You can't do anything client-side with PHP. You need Javascript for that. If you really need PHP (for instance to do a check to the database or something), you can use Javascript to do an Ajax call, and put the return value inside a div on the page.

How to send variables from a PHP script to another script using POST without forms?

I'm trying to write my first PHP script (hopefully). I want to send user input from a form inside an HTML page to a PHP script and validate them inside script. then, if there is any problem with input data, return to first page and highlight wrong fields. else go to another page (something like successful).
How do i send feedback from second script to first page without using forms?
In short, you'd have something like this:
<?php
if ($_SERVER['REQUEST_METHOD'] == 'POST') {
$errors = array();
$name = $_POST['name'];
if ($name !== 'Fred') {
$errors[] = 'Please enter "Fred"';
}
... validate more fields ...
if (count($errors) == 0) {
... form is ok ...
header('Location: everything_is_ok.php');
exit();
}
}
?>
<form action="<?php echo $_SERVER['SCRIPT_NAME'] ?>" method="POST">
Enter 'Fred': <input type="text" name="name" value="<?php echo htmlspecialchars($name) ?>" /><br />
<input type="submit" />
</form>
Basically: Have the form page submit back to itself. If everything's ok, redirect the user to another page. Otherwise redisplay the form.
Just make your Form POST to itself, then in your PHP check the values and if they are valid, don't display your form and do your submit code. If they are invalid, display the form with the values and errors displaying.
Reload the first page and send the feedback in the session, for example. If session['errors'] exist, echo them. Note you'll have to include some php tags in your html page anyway.
Use a session... here's a link to help you get started: http://www.tizag.com/phpT/phpsessions.php

How should I handle the case in which a username is already in use?

To practice PHP and MySQL development, I am attempting to create the user registration system for an online chess game.
What are the best practices for:
How I should handle the (likely) possibility that when a user tries to register, the username he has chosen is already in use, particularly when it comes to function return values? Should I make a separate SELECT query before the INSERT query?
How to handle varying page titles?($gPageTitle = '...'; require_once 'bgsheader.php'; is rather ugly)
(An excerpt of the code I have written so far is in the history.)
Do a separate SELECT to check whether the username is already in use before attempting to INSERT.
More importantly, I would suggest something like the following structure for the script you're writing. It has a strong separation of presentation logic (e.g. HTML) from your other processing (e.g. validation, database, business logic.) This is one important aspect of the model-view-controller paradigm and is generally considered a best-practice.
<?php
// The default state of the form is incomplete with no errors.
$title = "Registration";
$form_completed = false;
$errors = array();
// If the user is submitting the form ..
if ($_POST) {
// Validate the input.
// This includes checking if the username is taken.
$errors = validate_registration_form($_POST);
// If there are no errors.
if (!count($errors)) {
// Add the user.
add_user($_POST['username'], $_POST['password']);
// The user has completed.
$form_completed = true;
// Optionally you could redirect to another page here.
} else {
// Update the page title.
$title = "Registration, again!"
}
}
?>
<html>
<head>
<title>Great Site: <?= $title ?></title>
<body>
<?php if ($form_complete): ?>
<p>Thanks for registering!</p>
<?php else: ?>
<?php if (count($errors)): ?>
<ul>
<?php foreach ($errors as $error): ?>
<li><?= $error ?></li>
<?php endforeach; ?>
</ul>
<?php endif; ?>
<form method="post">
Username: <input type="text" name="username">
Password: <input type="password" name="password">
<input type="submit">
</form>
<?php endif; ?>
</body>
</html>
Well, one thing you can do instead of repeating code down near the bottom is this:
if( $result === true ) {
$gPageTitle = 'Registration successful';
$response = <p>You have successfully registered as ' . htmlspecialchars( $username ) . ' on this site.</p>';
} elseif( $result == 'exists' ) {
$gPageTitle = 'Username already taken';
$response = '<p>Someone is already using the username you have chosen. Please try using another one instead.</p>';
} else {
trigger_error('This should never happen');
}
require_once 'bgsheader.php';
echo $response;
require_once 'bgsfooter.php';
Also, you can return false rather than the string 'exists' in the function, not that it makes much difference.
Checking the error number isn't bad, I'm sure that's why it's an included feature. If you really wanted to do something different, you could check if there already is a user by that name by selecting the username. If no result exists, then insert the user, otherwise, give the error.
One thing I like to do with error handling on forms is save all the error strings into an array like $error['username'], $error['email'], etc., and then have it run through the error checking on each input individually to set all the error strings, and then have a function that does something like this:
function error($field)
{
global $error;
if(isset($error[$field]))
{
echo $error[$field];
}
}
and then call that after each field in the form to give error reporting on the form. Of course, the form page must submit to itself, but you could have all the error checking logic in a separate file and do an include if $_POST['whatever'] is set. If your form is formatted in a table or whatever, you could even do something like echo '<tr><td class="error">' . $error[$field] . '</td></tr>, and automatically insert another row directly below the field to hold the error if there is one.
Also, always remember to filter your inputs, even if it should be filtered automatically. Never pass post info directly into a DB without checking it out. I'd also suggest using the specific superglobal variable for the action, like $_POST rather than $_REQUEST, because $_REQUEST contains $_GET, $_POST, and $_COOKIE variables, and someone could feasibly do something strange like submit to the page with ?username=whatever after the page, and then you have both $_POST['username'] and $_GET['username'], and I'm not sure how $_REQUEST would handle that. Probably would make there be a $_REQUEST['username'][0] and $_REQUEST['username'][1].
Also, a bit about the page titles. Don't know if you have it set up like this but you can do something like this in your header:
$pageTitle = "My Website";
if(isset($gPageTitle))
{
$pageTitle .= "- $gPageTitle";
}
echo "<title>$pageTitle</title>";
Which would make the page load normally with "My Website" as the title, and append "- Username already exists" or whatever for "My Website - Username already exists" as the title when $gPageTitle is set.
I think the answer from Mr. Neigyl would require a separate trip to the database, which is not a good idea because it would only add performance overhead to yuor app.
I am not a PHP guru, but I know my way around it, although I don't recall the === operator. == I remember.
You could pass the function call directly into the IF statement.
if (addUser($username, $passwd));
I don't see anything wrong with using the $gPageTitle variable, but you will probably have to declare it "global" first and then use namespaces so you can actually access it within the "header.php" because "header.php" will not know how to address this page's variables.
Although I personally don't like messing with namespaces and I would rather call a function from the "header.php" and pass the page title into it
display_title($pgTitle);
or
display_title("Registration Successfull");
or
$header->display_title("Registration Successfull")
if you like OO style better
Let me know if that helps. :)
You should get into forms and allow your page to redirect to another page where you have there the 'insert username to database'.
Suppose the username entered is in a post variable such as $_POST['username'].
Have your database check where that username exist:
$res = mysql_query("SELECT * FROM table WHERE username='$_POST['username']'") or die(mysql_error());
if(mysql_num_rows($res) > 0) {
echo "Username exists.";
// more code to handle username exist
} else {
// ok here.
}
What is basically done is we check if your table already contains an existing username. mysql_num_rows($res) will return 0 if no username exist.

Categories