<?php
//Logic php is re-entrant. User enters data, db good, fields reset and message on status line.
//can enter again, have to add button to return to main menu.
//if db error, display error on status line, leave data intact.
//The form part is not display anything.
session_start();
error_reporting(E_ALL); // ALL KINDS OF ERROR
// (C) DISPLAY ERROR MESSAGES
ini_set("display_errors", 1);
require("db.php");
include("config.php");
if ($_SESSION["onlinestat"] == "0")
{
$_SESSION["onlinestat"] ="6";
}
else
{
$fname = $_POST['fname'];
$lname = $_POST['lname'];
$address = $_POST['address'];
$city = $_POST['city'];
$state = $_POST['state'];
$zipcode = $_POST['zipcode'];
$phone = $_POST['phone'];
$email = $_POST['email'];
try {
$stmt = $pdo->prepare("INSERT INTO contactstest (firstname, lastname, phone, email, address, city, state, zipcode) VALUES ('$fname','$lname','$phone','$email','$address','$city','$state','$zipcode')");
}
catch (Exception $e) {
// MySQL exception
$_SESSION["onlinemessage"] = $e->getMessage();
$_SESSION["onlinestat"] = "9";
}
try
{
$stmt->execute();
}
catch (Exception $e) {
// MySQL exception
$_SESSION["onlinemessage"] = $e->getMessage();
$_SESSION["onlinestat"] = "9";
}
$where = strpos($_SESSION["onlinemessage"],":");
if (!$where)
{
$_SESSION["onlinemessage"] = 'Thank You For your vote to oppose the Project';
$fname=$lname=$address=$city=$state=$zipcode=$phone=$email="";
$_SESSION["onlinestat"] = "1";
}
else
{
$len = strlen($_SESSION["onlinemessage"]) - $where;
$_SESSION["onlinemessage"] ="*ERROR* " . substr($_SESSION["onlinemessage"],$where+1,$len);
}
$status = $_SESSION["onlinemessage"];
}
?>
<html>
<head>
<style>
body {background-color: #008B8B;}
h3 {text-align: center;}
.error {color: #FF0000;}
.container {
width: 1000px;
margin: 50px auto;
background-color: white;
padding: 20px;
border-radius: 8px;
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
}
</style>
</head>
<body>
<div class="container">
<form action="/registertest/index.php" method="POST">
<p>
<label for="fname">First name:</label>
<input type="text" id="fname" size="40" name="fname" required>
<label for="lname">Last name:</label>
<input type="text" id="lname" size="40" name="lname" required>
</p>
<p>
<label for="address">Address: </label>
<input type="text" id="address" size="40" name="address" required>
</p>
<p>
<label for="city">City: </label>
<input type="text" id="city" size="40" name="city" required>
<label for="state">State:</label>
<input type="text" id="state" sie="20" name="state" required>
<label for="zip">Zipcode:</label>
<input type="text" id="zip" size="5" name="zipcode" maxlength="5" required>
</p>
<p>
<label for="email">Email: </label>
<input type="email" id="email" size="50" name="email">
</p>
<p>
<label for="phone">Phone: </label>
<input type="tel" id="phone" size="10" name="phone" maxlength="10">
</p>
<label for="status"> </label>
<input type="text" id="status" size="72" name="status">
</p>
<input type="submit" value="Submit" text-align: center; >
<input type="reset" value="Reset">
</form>
</div>
</body>
</html>
To post code on the forum, either put bbcode [code][/code] tags or markdown three back-ticks ``` on their own lines, above and below your code. I have edited your post above.
The page reloads and youre not redisplaying the POST values.
$_SESSION["onlinestat"] ="6";
}
This makes zero sense without context. I don’t get what is 6
just used to force 1st time thru. set to 0, then on 1st pass to 6. Re-entrance means data is populated, do the insert. set 1 is success 9 means error in mysql.
I see. That makes sense now. Mebby you can save them in constants and add comment to explain the lifecycle. This very good approach for future in case you or someone else looking at the code.
// comment to explain
const STAT_INITIAL = '0';
const STAT_FIRST_PASS = '6';
Did you manage to get the form work as intended yet?
Noted, Correct.
The form works in practice. But the status line does not show up. Actual debugging shows that status is populated.
for instance success, and should fall thru, with all fields reset and status line.
Thank You For your vote to oppose the Project’;
<?php
$status = $_SESSION["onlinemessage"];
?>
<html>
<head>
</head>
<body>
<div class="container">
<form action="/registertest/index.php" method="POST">
<p>
<label for="fname">First name:</label>
<input type="text" id="fname" size="40" name="fname" required>
<label for="lname">Last name:</label>
<input type="text" id="lname" size="40" name="lname" required>
</p>
<p>
<label for="address">Address: </label>
<input type="text" id="address" size="40" name="address" required>
</p>
<p>
<label for="city">City: </label>
<input type="text" id="city" size="40" name="city" required>
<label for="state">State:</label>
<select name="state" id="state">
<?php
$stmt = $pdo->query("SELECT * FROM StateTable");
while ($row = $stmt->fetch()) {
if($row['name'] == "Texas"){
$selected = "selected";
}else{
$selected = "";
}
$output = ' <option value="' . $row['name'] . '">' . $row['abbv'] . "</option>" . "\r\n";
//Echo output
echo $output;
}
?>
</select>
<label for="zip"Zipcode:</label>
<input type="text" id="zip" size="5" name="zipcode" maxlength="5" required>
</p>
<p>
<label for="email">Email: </label>
<input type="email" id="email" size="50" name="email">
</p>
<p>
<label for="phone">Phone: </label>
<input type="tel" id="phone" size="10" name="phone" maxlength="10">
</p>
<label for="status"> </label>
<input type="text" id="status" size="72" name="status">
</p>
<input type="submit" value="Submit" text-align: center; >
<input type="reset" value="Reset">
<input type="button" value="Back">
</form>
</div>
</body>
</html>
</code>
There is no code in your form to output/echo any of the php values, so, of course nothing shows up.
This is not the logic that I wrote out for you. Here’s a collection of the previous information -
The redirect upon successful completion of the post method form processing code should be to the exact same URL of the current page to cause a get request for that page. This prevents the browser from trying to resubmit the form data should that page get browsed back to or reloaded.
// redirect to the exact same URL of the current page to cause a get request - Post, Redirect, Get (PRG)
die(header(Refresh:0));
To display a one-time success message, either store the message text or a flag value in a session variable, before you perform the redirect, then test for this session variable, display the success message, and clear the session variable at the appropriate location in the html document.
For user/validation errors, you should store them in an array using the field name as the array index. At the end of the form processing code, if there are no errors (the array is empty), perform the redirect. If there are errors the code will continue on to (re)display the html document, where you can test for and display the user/validation errors, either all at once or individually adjacent to the field they correspond to, then redisplay the form, populating the field values with the submitted form data, so that the user just needs to correct any errors and can resubmit the form.
One of the points for the redirect is that it causes a get request for the page. Since there will not be any $_POST data for a get request, there’s no need to clear anything. Keep It Simple (KISS.)
Here’s an additional list of points for the posted code -
- Php’s error related settings should be in the php.ini on your system, so that they can be set or changed at a single point, without needing to go trough all the files that might be setting them and edit the code.
- If you need to put php’s error related settings in your code, put them before all other php statements. If the session_start() produces an error, you would want that to be reported and displayed.
- Use ‘require’ for things your code must have.
- Require/include are not functions. The () around the path/filename do nothing and should be removed.
- Post method form processing code needs to detect if a post method form has been submitted before referencing any of the form data.
- You should keep the form data as a set in a php array variable, then operate on elements in this array variable throughout the rest of the code, i.e. don’t write out line after line of code copying variables to other variables.
- You need to trim all user input data, mainly so that you can detect if all white-space characters were entered, before validate it.
- You need to validate all input data, on the server, before using it.
- As already written in a previous thread, do NOT put dynamic values directly into sql query statements. Use a prepared query. What you are preparing in this code is not a prepared query.
- There’s no point in catching and handling an exception from the prepare() call. Any prepare error would be due to a programming mistake and should not be displayed on a live/public server.
- There’s no need to clear a bunch of variables in your code, if you do what I wrote and perform a redirect to the exact same URL of the current page, because there will not be any $_POST data after the redirect. That’s one of the points of the PRG pattern.
- If you put the closing
</label>tag after the form field it corresponds to, you can leave out the for=’…’ attributes and the corresponding id=’…’ attributes. - To get a form to submit to the same page it is on, simply leave the entire action attribute out of the form tag.
- You need to validate the resulting web pages at validator.w3.org
- Having a form field for the status (success message or errors) doesn’t make any sense. This is content, not form data.
- Any dynamic value you output in a html context needs to have htmlentities() applied to the value right before or as it is being output, to help prevent cross site scripting.
And, finally, here is an example of a Create/insert form and form processing code that demonstrates the points that have been made -
<?php
// example code for a Create CRUD operation
// initialization
session_start();
$post = []; // array to hold a trimmed working copy of the form data
$errors = []; // array to hold user/validation errors
require 'pdo_connection.php';
// post method form processing
if($_SERVER['REQUEST_METHOD'] === 'POST')
{
// trim all the input data at once
$post = array_map('trim',$_POST); // if any field is an array, use a recursive trim call-back function here instead of php's trim
switch($post['action'])
{
case 'create':
// validate input data, storing user/validation errors in $errors, using the field name as the array index
if($post['username'] === '')
{
$errors['username'] = 'Username is required';
}
if($post['email'] === '')
{
$errors['email'] = 'Email is required';
}
// if no errors, use the input data
if(empty($errors))
{
$sql = "INSERT users (username, email) VALUE (?, ?)";
$stmt = $pdo->prepare($sql);
// since this query could result in a duplicate index error for column(s) that must be unique (defined as a unique index in the database table)
// you would have a 'local' try/catch block for the execution of this query that tests for a duplicate index error number
// and sets up a message(s) for the user letting them know which column(s) contain duplicate values
// if there is a single unique index/column, you know that the error was for that column
// if there are multiple unique indexes/columns, you would build and execute a SELECT query to determine which columns contain duplicate values
try { // a 'local' try/catch to handle a specific error
$stmt->execute([ $post['username'], $post['email'] ]);
} catch (PDOException $e) {
if($e->errorInfo[1] != 1062) // duplicate index error number
{
throw $e; // re-throw the exception if not handled by this logic
}
// this example is for a single unique column, username
$errors['username'] = "The username already exists.";
// the code necessary to detect which of multiple columns are duplicate values is beyond the scope of this example
}
}
// if no errors, success
if(empty($errors))
{
$_SESSION['success_message'] = 'Data has been inserted.';
// redirect to the exact same URL of the current page to cause a get request - Post, Redirect, Get (PRG)
die(header("Refresh:0"));
}
break;
}
}
// get method business logic - get/produce data needed to display the page
// html document
// only the parts necessary for this example are shown
?>
<?php
// display any success message
if(!empty($_SESSION['success_message']))
{
echo "<p>".htmlentities($_SESSION['success_message'])."</p>";
unset($_SESSION['success_message']);
}
?>
<?php
// display any errors
if(!empty($errors))
{
$er = array_map('htmlentities',$errors);
echo "<p>".implode('<br>',$er)."</p>";
}
?>
<?php
// display the form
?>
<form method='post'>
<input type='hidden' name='action' value='create'>
<label>Username: <input type='text' name='username' value='<?=htmlentities($post['username']??'')?>'></label><br><br>
<label>Email: <input type='text' name='email' value='<?=htmlentities($post['email']??'')?>'></label><br><br>
<button type='submit'>Create</button>
</form>