I have a script to add companies and categories to a database, however it only works first time. When I try to add a second company, it fails on the final error check after passing all other error checks. The category is added successfully to the categories table but the company and its details do not get added to the companies table.
Is this likely to be a code error or an error in my database construction?
Here is the final error check and mysql query:
if (empty($errors)) { // If everything's OK.
// Add the company to the database:
$q = 'INSERT INTO companies (category_id, company_name, phone, email, website, address_1, address_2, address_3, postcode, description, image_name) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)';
$stmt = mysqli_prepare($dbc, $q);
mysqli_stmt_bind_param($stmt, 'issssssssss', $catid, $cn, $p, $e, $w, $a1, $a2, $a3, $pc, $d, $i);
mysqli_stmt_execute($stmt);
// Check the results...
if (mysqli_stmt_affected_rows($stmt) == 1) {
// Print a message:
echo '<p>The company has been added.</p>';
// Rename the image:
$id = mysqli_stmt_insert_id($stmt); // Get the company ID.
rename ($temp, "../../../uploads/$id");
// Clear $_POST:
$_POST = array();
} else { // Error!
echo '<p style="font-weight: bold; color: #C00">Your submission could not be processed due to a system error.</p>';
}
mysqli_stmt_close($stmt);
} // End of $errors IF.
Here is the entire code:
<?php
require_once ('../../../mysqli_connect.php');
if (isset($_POST['submitted'])) { // Handle the form.
// Validate the incoming data...
$errors = array();
// Check for a company name:
if (!empty($_POST['company_name'])) {
$cn = trim($_POST['company_name']);
} else {
$errors[] = 'Please enter the company\'s name!';
}
// Check for an image:
if (is_uploaded_file ($_FILES['image']['tmp_name'])) {
// Create a temporary file name:
$temp = '../../../uploads/' . md5($_FILES['image']['name']);
// Move the file over:
if (move_uploaded_file($_FILES['image']['tmp_name'], $temp)) {
echo '<p>The file has been uploaded!</p>';
// Set the $i variable to the image's name:
$i = $_FILES['image']['name'];
} else { // Couldn't move the file over.
$errors[] = 'The file could not be moved.';
$temp = $_FILES['image']['tmp_name'];
}
} else { // No uploaded file.
$errors[] = 'No file was uploaded.';
$temp = NULL;
}
// Validate the category...
if (isset($_POST['category']) && ($_POST['category'] == 'new') ) {
// If it's a new category, add the category to the database...
// Check for a category name...
if (!empty($_POST['category_name'])) {
$catn = trim($_POST['category_name']);
// Add the category to the database:
$q = 'INSERT INTO categories (category_name) VALUES (?)';
$stmt = mysqli_prepare($dbc, $q);
mysqli_stmt_bind_param($stmt, 's', $catn);
mysqli_stmt_execute($stmt);
// Check the results....
if (mysqli_stmt_affected_rows($stmt) == 1) {
echo '<p>The category has been added.</p>';
$catid = mysqli_stmt_insert_id($stmt); // Get the category ID.
} else { // Error!
$errors[] = 'The new category could not be added to the database!';
}
// Close this prepared statement:
mysqli_stmt_close($stmt);
} else { // No category name value.
$errors[] = 'Please enter the category\'s name!';
}
} elseif ( isset($_POST['category']) && ($_POST['category'] == 'existing') && ($_POST['existing'] > 0) ) { // Existing category.
$catid = (int) $_POST['existing'];
} else { // No category selected.
$errors[] = 'Please enter or select the category\'s name!';
}
if (empty($errors)) { // If everything's OK.
// Add the company to the database:
$q = 'INSERT INTO companies (category_id, company_name, image_name) VALUES (?, ?, ?)';
$stmt = mysqli_prepare($dbc, $q);
mysqli_stmt_bind_param($stmt, 'iss', $catid, $cn, $i);
mysqli_stmt_execute($stmt);
// Check the results...
if (mysqli_stmt_affected_rows($stmt) == 1) {
// Print a message:
echo '<p>The company has been added.</p>';
// Rename the image:
$id = mysqli_stmt_insert_id($stmt); // Get the company ID.
rename ($temp, "../../../uploads/$id");
// Clear $_POST:
$_POST = array();
} else { // Error!
echo '<p style="font-weight: bold; color: #C00">Your submission could not be processed due to a system error.</p>';
}
mysqli_stmt_close($stmt);
} // End of $errors IF.
// Delete the uploaded file if it still exists:
if ( isset($temp) && file_exists ($temp) && is_file($temp) ) {
unlink ($temp);
}
} // End of the submission IF.
// Check for any errors and print them:
if ( !empty($errors) && is_array($errors) ) {
echo '<h1>Error!</h1>
<p style="font-weight: bold; color: #C00">The following error(s) occurred:<br />';
foreach ($errors as $msg) {
echo " - $msg<br />\n";
}
echo 'Please reselect the company image and try again.</p>';
}
// Display the form...
?>
I needed to specify the primary key as auto-increment, in this case it is the company_id field.
A simple way to add detailed error checking is to insert
mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
before the mysqli_connection is made.
Related
I'm trying to set a condition wherein if the 'filefield' is empty, it will skip the insert in DB as it is only an option and just proceed in inserting of 'name' and 'description' in the DB, which will never be empty.
<?php
include("connection.php");
if (isset($_POST['submit']))
{
$name = mysqli_real_escape_string($conn, $_POST['name']);
$description = mysqli_real_escape_string($conn, $_POST['description']);
if ($name == '' || $description == '' )
{
$error = 'ERROR: Please fill required fields!';
renderForm($name, $description);
}
else
{
if(!empty($_FILES['filefield'])){
if(isset($_FILES['filefield'])){
$file=$_FILES['filefield'];
$upload_directory='uploads/';
$ext_str = "gif,jpg,jpeg,mp3,tiff,bmp,doc,docx,ppt,pptx,txt,pdf";
$allowed_extensions=explode(',',$ext_str);
$ext = substr($file['name'], strrpos($file['name'], '.') + 1);
if (!in_array($ext, $allowed_extensions) )
{
echo '<script language="javascript">';
echo 'alert("file type not allowed for upload")';
echo '</script>';
exit();
}
$path=md5(microtime()).'.'.$ext;
if(move_uploaded_file($file['tmp_name'],$upload_directory.$path)){
$filefield = $_FILES["filefield"]["name"];
$path = $path."/".$filefield;
}
}
}
}
if (!empty($_FILES['filefield']) || !isset($_FILES['filefield'])) {
$query = "INSERT INTO `item`(`name`, `description`, `path`) VALUES ('$name','$description','$path')";
}
else {
$query = "INSERT INTO `item`(`name`, `description`) VALUES ('$name','$description')";
}
$result = mysqli_query($conn, $query);
if($result)
{
echo '<script language="javascript">';
echo 'alert("Success!")';
echo '</script>';
exit();
}
}
?>
I'm not sure how to proceed with the condition. Any help is highly appreciated.
First, close off all of your logic, including if(move_uploaded_file), so that the $query is competely outside of any conditionals. Then it's just a matters of checking whether the filefield was filled out or not. If it's not empty, your $query insert all three fields. If it is, your $query only inserts $name and $description.
This can be seen in the following (heavily cut-down) code:
/* Existing logic */
else
{
if (!empty($_FILES['filefield'])) {
if (isset($_FILES['filefield'])) {
if (move_uploaded_file($file['tmp_name'], $upload_directory.$path)) {
...
$path = $path."/".$filefield;
}
}
}
}
/* Modified logic */
if (!empty($_FILES['filefield']) || !isset($_FILES['filefield'])) {
$query = "INSERT INTO `item`(`name`, `description`, `path`) VALUES ('$name','$description','$path')";
}
else {
$query = "INSERT INTO `item`(`name`, `description`) VALUES ('$name','$description')";
}
$result = mysqli_query($conn, $query);
I have this code on "insert.php":
if ($stmt = $GLOBALS['mysqli']->prepare("INSERT INTO table1(iduser, title, msg, anonim, ip, iduniversity) VALUES (?,?,?,?,?,?)")) {
$stmt->bind_param("issisi", $_SESSION['iduser'], $_POST['title'], $_POST['msg'], $anonim, getIP(), $_SESSION['iduniversity']);
if ($stmt->execute()) {
$idmsg = $GLOBALS['mysqli']->insert_id;
$i = 0;
$stmt2 = $GLOBALS['mysqli']->prepare("INSERT INTO tag(idmsg, tag) VALUES(?,?)");
foreach ($tags as $tag) {
if ($tag != '') {
$stmt2->bind_param("is", $idmsg, $tag);
if ($stmt2->execute()) {
$i++;
}
}
}
$stmt2->close();
$stmt->close();
mysqli_close($GLOBALS['mysqli']);
sendFile($idmsg);
header("Location: /public/watch_msg.php?idmsg=" . $idmsg);
exit();
} else {
exit("Ops! Ocorreu algum erro. COD1370");
}
} else {
exit("Ops! Ocorreu algum erro. COD1371");
}
So, everything is working fine, except that sometimes when it redirects to "watch_msg.php" the message seems not to be on the database yet. When this happens, as soon as I refresh the page, everything is there!
First thing I thought is that there could be a race-condition somewhere, but I read in another question that PHP is sequential, and as I close both statements and connection before the redirect (so that used tables should be unlocked), why i'm getting this result somethimes? What i'm doing wrong?
Also, no functions outputs anything, but "sendFile" saves an image if the user sends one, so headers should be fine (it also gives me the error when I comment the function).
Code on watch_msg:
$msg = NULL;
$tags = NULL;
$coments = NULL;
$data_high = date("Y-m-d H:i:s");
$iduser;
if ($loggedin) { //If logged in
$idmsg = filter_input(INPUT_GET, 'idmsg', FILTER_SANITIZE_STRING);
$iduser = $_SESSION['iduser'];
$query = "SELECT * FROM table1 WHERE iduser = ? AND idmsg = ? AND datemsg < ?";
$stmt = $GLOBALS['mysqli']->prepare($query);
$stmt->bind_param("iis", $iduser, $idmsg, $data_high);
if ($stmt->execute()) {
$msg = mysqli_fetch_assoc($stmt->get_result());
if ($msg === NULL) {
exit('This message doesn\'t exists');
}
...
} else {
echo "Error.";
}
}
I am attempting to create a simple form that updates a row in a MYSQL database based on what ID the row is.
I have managed to get the form and updating values working, but for one of my variables I need its new value to be added to it, based on the values of two other variables. (So like $currPoints = $currPoints+$addPoints-$remPoints;).
The problem I am facing is that whenever the form is submitted, $currPoints is either resetting to 0, then adding and subtracting the other values, or the value of $cuurPoints isn't being found so that it cannot add to it's original value.
I am not sure where specifically in my code I am going wrong so I will paste the whole page if that is okay!
My form function. This get's called on page load:
// creates the form
function renderForm($name = '', $currPoints = '', $addPoints = '', $remPoints = '', $reason = '', $error = '', $id = '')
{ ?>
<title>
<?php if ($id != '') { echo "Edit Punk"; } else { echo "New Punk"; } ?>
</title>
<h1><?php if ($id != '') { echo "Edit Punk"; } else { echo "New Punk"; } ?></h1>
<?php if ($error != '') {
echo "<div style='padding:4px; border:1px solid red; color:red'>" . $error
. "</div>";
} ?>
<form name="pointsForm" action="" method="post" style="margin-top:50px;">
<?php if ($id != '') { ?>
<input type="hidden" name="id" value="<?php echo $id; ?>" />
<p>Name: <?php echo $name; ?> / <?php echo $currPoints; ?></p>
<?php } ?>
<input type="number" name="addPoints" placeholder="Add Punk Points">
<input type="number" name="remPoints" placeholder="Remove Punk Points">
<input type="text" name="reason" placeholder="Reason">
<input type="submit" name="submit" value="Update Punk Points">
</form>
</body>
</html>
<script>
$(function() {
$('form[name="pointsForm"]').submit(function(e) {
var reason = $('form[name="pointsForm"] input[name="reason"]').val();
if ( reason == '') {
e.preventDefault();
window.alert("Enter a reason, fool!")
}
});
});
</script>
<?php
}
Then my PHP for editing a record:
Where I get the variables from the URL/form I have added $currPoints = $currPoints+$addPoints-$remPoints;
Then on my bind_param is just add $currPoints.
I believe I am going wrong somewhere around these lines... or where I SET currPoints = ? . should that be something else?
Forgive me I am just learning PHP.
/*
EDIT RECORD
*/
// if the 'id' variable is set in the URL, we know that we need to edit a record
if (isset($_GET['id']))
{
// if the form's submit button is clicked, we need to process the form
if (isset($_POST['submit']))
{
// make sure the 'id' in the URL is valid
if (is_numeric($_POST['id']))
{
// get variables from the URL/form
$id = $_POST['id'];
$addPoints = htmlentities($_POST['addPoints'], ENT_QUOTES);
$remPoints = htmlentities($_POST['remPoints'], ENT_QUOTES);
$reason = htmlentities($_POST['reason'], ENT_QUOTES);
$currPoints = $currPoints+$addPoints-$remPoints;
// if everything is fine, update the record in the database
if ($stmt = $mysqli->prepare("UPDATE points SET currPoints = ? , addPoints = ?, remPoints = ?, reason = ?
WHERE id=?"))
{
$stmt->bind_param("iiisi", $currPoints, $addPoints, $remPoints, $reason, $id);
$stmt->execute();
$stmt->close();
}
// show an error message if the query has an error
else
{
echo "ERROR: could not prepare SQL statement.";
}
// redirect the user once the form is updated
header("Location: index.php");
}
// if the 'id' variable is not valid, show an error message
else
{
echo "Error!";
}
}
// if the form hasn't been submitted yet, get the info from the database and show the form
else
{
// make sure the 'id' value is valid
if (is_numeric($_GET['id']) && $_GET['id'] > 0)
{
// get 'id' from URL
$id = $_GET['id'];
// get the record from the database
if($stmt = $mysqli->prepare("SELECT * FROM points WHERE id=?"))
{
$stmt->bind_param("i", $id);
$stmt->execute();
$stmt->bind_result($id, $name, $currPoints, $addPoints, $remPoints, $reason, $date);
$stmt->fetch();
// show the form
renderForm($name, $currPoints, $addPoints, $remPoints, $reason, NULL, $id);
$stmt->close();
}
// show an error if the query has an error
else
{
echo "Error: could not prepare SQL statement";
}
}
// if the 'id' value is not valid, redirect the user back to the view.php page
else
{
header("Location: index.php");
}
}
}
?>
Sorry If I have been too vague. Please let me know if you need more information.
Thank you!
Oh found the error I think, you are never defining $currPoints before you try and use it, so you can't have $currPoints = $currPoints+.. because it isn't created yet. PHP more or less so will read line by line, so you have to query the SQL table and set $currPoints equal to the value from your database before you do $currPoints = $currPoints+$addPoints-$remPoints;
Ok, this probably won't work, but you should be able to figure out what I changed and adapt your code to work with it. I wouldn't say it's the 'proper' way, but it is a little easier to read and see what the code is doing when you have the if statements at the top to deal with what data is submitted vs not submitted.
if (!isset($_GET['id'] || !isset($_POST['submit'])))
{
echo "No Data!"
return;
}
if (!is_numeric($_POST['id']))
{
echo "Invalid ID!";
header("Location: index.php");
return;
}
// get variables from the URL/form
$id = $_POST['id'];
$addPoints = htmlentities($_POST['addPoints'], ENT_QUOTES);
$remPoints = htmlentities($_POST['remPoints'], ENT_QUOTES);
$reason = htmlentities($_POST['reason'], ENT_QUOTES);
$currPoints = 0;
//Check what the current points are first
// make sure the 'id' value is valid also
if (is_numeric($_GET['id']) && $_GET['id'] > 0)
{
// get 'id' from URL
$id = $_GET['id'];
// get the record from the database
if($stmt = $mysqli->prepare("SELECT * FROM points WHERE id=?"))
{
$stmt->bind_param("i", $id);
$stmt->execute();
$stmt->bind_result($id, $name, $currPoints, $addPoints, $remPoints, $reason, $date);
$stmt->fetch();
// show the form
renderForm($name, $currPoints, $addPoints, $remPoints, $reason, NULL, $id);
$stmt->close();
}
else
echo "Error: could not prepare SQL statement";
}
//Now update currPoints
$currPoints += $addPoints-$remPoints;
// if everything is fine, update the record in the database
if ($stmt = $mysqli->prepare("UPDATE points SET currPoints = ? , addPoints = ?, remPoints = ?, reason = ?
WHERE id=?"))
{
$stmt->bind_param("iiisi", $currPoints, $addPoints, $remPoints, $reason, $id);
$stmt->execute();
$stmt->close();
}
else
echo "ERROR: could not prepare SQL statement.";
// redirect the user once the form is updated
header("Location: index.php");
I have a validation with some if/else statements.
<?php
if (isset($_POST["join"])) {
if ($userpoint < $lessonpoint) { //pt
echo "you need more points";
} //pt
else { //has enough point
if ($row['num'] > 0) { //check if user took this lesson
echo "you took this lesson before.";
} //check if user took this lesson ends
else { //then let him apply to database
//define post:
$postvalue = (int)$_POST["postvalue"];
//and check
if($postvalue == '' || $postvalue <= 0 || $postvalue > $minimumpostvalue || $postvalue == is_int($postvalue)) { //check post
echo "Error.";
} //checkpost ends.
else { //insert
$sql = "INSERT into etc... VALUES (?, ?, ?)";
if($sql){ //to another database
$artibir = "UPDATE etc.";
echo "Done.";
} // to another database
}//insert
} //let him apply
} //has enough point
} //if post isset join
?>
This works very well.
But I want to echo out another error message for this condition: $postvalue > $minimumpostvalue
While trying it I get lost inside the if/else statements.
Wherever I put new statement I'm having an error.
All variables are defined.
Where and how can I place $postvalue > $minimumpostvalue to echo a different error message?
<?php
if (isset($_POST["join"])) {
if ($userpoint < $lessonpoint) { //pt
echo "you need more points";
} //pt
else { //has enough point
if ($row['num'] > 0) { //check if user took this lesson
echo "you took this lesson before.";
} //check if user took this lesson ends
else { //then let him apply to database
//define post:
$postvalue = (int) $_POST["postvalue"];
//and check
if ($postvalue == '' || $postvalue <= 0 || $postvalue > $minimumpostvalue || $postvalue == is_int($postvalue)) { //check post
if ($postvalue > $minimumpostvalue) {
echo "Another Error.";
}
else {
echo "Error.";
}
} //checkpost ends.
else { //insert
$sql = "INSERT into etc... VALUES (?, ?, ?)";
if ($sql) { //to another database
$artibir = "UPDATE etc.";
echo "Done.";
} // to another database
} //insert
} //let him apply
} //has enough point
} //if post isset join
?>
This is another variation without exceptions.
As soon as $valid becomes false, it will skip the next validation.
<?php
$valid = true;
$error = '';
if ($valid && !isset($_POST["join"])) {
$error = 'Not a join post request';
$valid = false;
}
if ($valid && ($userpoint < $lessonpoint)) {
$error = 'You need more points';
$valid = false;
}
...
if($valid) {
// Database insert; redirect
} else {
// User error feedback
}
//and check
if ($postvalue > $minimumpostvalue) { //check exception
echo "Error 1.";
} elseif ($postvalue == '' || $postvalue <= 0 || $postvalue == is_int($postvalue)) { //check the rest
echo "Error 2.";
} //checkpost ends.
This is untested code, and more an example of how to avoid nested if statements.
The point is to find to state the conditions you have an error state early and exit as soon as you can, at best by throwing an exception and avoiding else statements.
For simplicity I used only \RunTimeException(), yet I would most likely define my own exception depending on the case. The exception then can be caught and depending on their type show a different error page.
/**
* #param int $postvalue
* #param int $minimumpostvalue
*/
function saveToDatabase($postvalue)
{
if ($postvalue == '' || $postvalue <= 0 || $postvalue == is_int($postvalue)) {
throw new \RuntimeException('Error 2');
}
$sql = "INSERT into etc... VALUES (?, ?, ?)";
if ($sql) {
$artibir = "UPDATE etc.";
}
}
if (!isset($_POST["join"])) {
throw new \RuntimeException('Not a join post request');
}
if ($userpoint < $lessonpoint) {
throw new \RuntimeException('You need more points');
}
$userHasTakenCourse = $row['num'] > 0;
if ($userHasTakenCourse) {
throw new \RuntimeException('User has already taken the course.');
}
$postvalue = (int) $_POST["postvalue"];
if ($postvalue > $minimumpostvalue) {
throw new \RuntimeException('Error 1');
}
saveToDatabase($postvalue);
When the user submits the form, the form information is posted to a php file and the php file redirects the user straight away to the next webpage once the form is submitted by using the header function. I have already validated the form using HTML and Javascript however the PHP has validation in it so that any errors that get past the Javascript and HTML are identified and the user is notified, however this is not possible at the minute as the user is redirected before they are notified.
How would I identify the user if the PHP locates an error?
Is it necessary as will the only errors be by people who are intentionally trying to be malicious?
My code is:
<?php
header("location: (next webpage)");
if(isset($_POST['submit'])){
$data_missing = array();
if(empty($_POST['email_banned'])){
// Adds name to array
$data_missing[] = 'Email';
} else {
// Trim white space from the name and store the name
$email_banned = trim($_POST['email_banned']);
}
if(empty($_POST['notes'])){
// Adds name to array
$data_missing[] = 'Notes';
} else {
// Trim white space from the name and store the name
$notes = trim($_POST['notes']);
}
if(empty($data_missing)){
require_once('mysqli_connect.php');
$query = "INSERT INTO banned_emails (id, email_banned, created_on, notes) VALUES ( NULL, ?, NOW(), ?)";
$stmt = mysqli_prepare($dbc, $query);
//i Interger
//d Doubles
//s Everything Else
mysqli_stmt_bind_param($stmt, "ss", $email_banned, $notes);
mysqli_stmt_execute($stmt);
$affected_rows = mysqli_stmt_affected_rows($stmt);
if($affected_rows == 1){
echo 'Student Entered';
mysqli_stmt_close($stmt);
mysqli_close($dbc);
} else {
echo 'Error Occurred<br />';
echo mysqli_error();
mysqli_stmt_close($stmt);
mysqli_close($dbc);
}
} else {
echo 'You need to enter the following data<br />';
foreach($data_missing as $missing){
echo "$missing<br />";
}
}
}
?>
Thanks :)
You can use $_SESSION to store errors, and retrieve them later.
$_SESSION['errors'] = array('an error message', 'a second error message');
Then in the script the user has been redirected to :
while($err = array_shift($_SESSION['errors'])){
?>
<p class='p_error'><?=$err?></p>
<?php
}