This is my code. But I have a problem.
if ($kundevor!="" or $kundenach!="")
{
if ($kundevor=="")
{
$kundezusatz=" WHERE Nachname LIKE '$kundenach%'";
}
else if ($kundenach=="")
{
$kundezusatz=" WHERE Vorname LIKE '$kundevor%'";
}
else
{
$kundezusatz=" WHERE (Vorname LIKE '$kundevor%') OR (Nachname LIKE '$kundenach%')";
}
$sql = $dbh->prepare ("SELECT Nachname, Vorname FROM tblkunden $kundezusatz ");
$sql->execute() or die("SQL Fehler in: ".$sql->queryString." <br /> ".$sql->errorInfo()[2]);
echo "<table>";
echo '<p class="abfrage2">Abfrage 3:</p>';
echo"<tr><th>Nachname</th><th>Vorname</th></tr>";
while($ds = $sql->fetch())
{
echo "<tr><td>$ds[Nachname]</td><td>$ds[Vorname]</td></tr>";
}
}
If someone for example types a letter into my form which is neither like the "Vorname" (= first name) nor like the "Nachname" (= last name) it displays nothing. But I want to have a message like "Sorry, but none of your letters match with the Names in the database".
How can you achieve that in this code?
A remark: Your statement preparation is wrongly applied and looses its purpose: to avoid sql injection. No values should be directly passed into the sql statement. Instead, parameter markers (named or not) should be defined in the statement - as placeholders. For each of these markers the corresponding value must be passed either by calling the bindValue method, or the bindParam method, or by defining it as an element value in an array passed directly as argument to the PDOStatement::execute method.
Some suggestions:
You might also want to read this and this articles on how to apply error/exception handling and this article on applying prepared statements.
Avoid creating html code from PHP. Separate the php code from the html code.
Instead of mixing db fetching code with html code (like you did with while($ds = $sql->fetch()){...}), you should fetch all db data into an array (in the php code part) and iterate through it further (in the html code part).
Below is a code version in which I implement a solution to your task/question. I used my own naming/coding conventions (inclusive for the db table) though - so, as I would apply them in my own project.
Since you didn't specified which library you are using (PDO or mysqli) and because only PDO has the PDOStatement::errorInfo method, I deducted that you are using the PDO library. Therefore, my code uses PDO.
kunden.php
<?php
require 'connection.php';
if (isset($_POST['submit'])) {
$nachname = isset($_POST['nachname']) ? $_POST['nachname'] : '';
$vorname = isset($_POST['vorname']) ? $_POST['vorname'] : '';
if (empty($nachname) && empty($vorname)) {
$errors[] = 'Please provide either the first name, or the last name, or both.';
}
if (!isset($errors)) {
// Array used for creating the WHERE conditions in the sql statement.
$whereConditions = [];
/*
* Used for injecting the proper values for the named parameter markers found
* in the sql statement. It is passed as argument to the PDOStatement::execute method.
*/
$inputParameters = [];
if (!empty($nachname)) {
$whereConditions[] = 'nachname LIKE :nachname';
$inputParameters[] = '%' . $nachname . '%';
}
if (!empty($vorname)) {
$whereConditions[] = 'vorname LIKE :vorname';
$inputParameters[] = '%' . $vorname . '%';
}
$sql = sprintf(
'SELECT kunde_id, nachname, vorname FROM kunden WHERE %s'
, implode(' OR ', $whereConditions)
);
$statement = $connection->prepare($sql);
$statement->execute($inputParameters);
$kunden = $statement->fetchAll(PDO::FETCH_ASSOC);
if (!$kunden) {
$errors[] = 'No clients found for your request.';
}
}
}
?>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=yes" />
<meta charset="UTF-8" />
<!-- The above 3 meta tags must come first in the head -->
<title>Demo</title>
<script src="https://code.jquery.com/jquery-3.2.1.min.js" type="text/javascript"></script>
<script type="text/javascript">
$(document).ready(function () {
$('#nachname').focus();
});
</script>
<style type="text/css">
body {
padding: 30px;
}
label {
/*display: block;*/
font-weight: 400;
}
input[type="text"] {
display: block;
margin-bottom: 20px;
}
button {
display: block;
padding: 7px 10px;
background-color: #8daf15;
color: #fff;
border: none;
}
.messages {
margin-bottom: 20px;
}
.messages .error {
color: #c00;
}
.kunden-list {
margin-top: 20px;
border-collapse: separate;
}
.kunden-list thead th {
padding: 10px;
background-color: #ccc;
}
.kunden-list tbody td {
padding: 10px;
}
</style>
</head>
<body>
<div class="messages">
<?php
if (isset($errors)) {
foreach ($errors as $error) {
?>
<div class="error">
<?php echo $error; ?>
</div>
<?php
}
}
?>
</div>
<div class="form-container">
<form action="" method="post">
<label for="nachname">Nachname:</label>
<input type="text" id="nachname" name="nachname" value="<?php echo isset($nachname) ? $nachname : ''; ?>">
<label for="vorname">Vorname:</label>
<input type="text" id="vorname" name="vorname" value="<?php echo isset($vorname) ? $vorname : ''; ?>">
<button type="submit" name="submit" value="submit">
Senden
</button>
</form>
</div>
<?php
if (isset($kunden) && $kunden) {
?>
<table class="kunden-list">
<thead>
<tr>
<th>ID</th>
<th>Nachname</th>
<th>Vorname</th>
</tr>
</thead>
<tbody>
<?php
foreach ($kunden as $kunde) {
$kundeId = $kunde['kunde_id'];
$nachname = $kunde['nachname'];
$vorname = $kunde['vorname'];
?>
<tr>
<td><?php echo $kundeId; ?></td>
<td><?php echo $nachname; ?></td>
<td><?php echo $vorname; ?></td>
</tr>
<?php
}
?>
</tbody>
</table>
<?php
}
?>
</body>
</html>
connection.php
<?php
// Db configs.
define('HOST', 'localhost');
define('PORT', 3306);
define('DATABASE', 'yourDb');
define('USERNAME', 'yourUser');
define('PASSWORD', 'yourPassword');
define('CHARSET', 'utf8');
/*
* Create a PDO instance as db connection to db.
*
* #link http://php.net/manual/en/class.pdo.php
* #link http://php.net/manual/en/pdo.constants.php
* #link http://php.net/manual/en/pdo.error-handling.php
* #link http://php.net/manual/en/pdo.connections.php
*/
$connection = new PDO(
sprintf('mysql:host=%s;port=%s;dbname=%s;charset=%s', HOST, PORT, DATABASE, CHARSET)
, USERNAME
, PASSWORD
, [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_EMULATE_PREPARES => FALSE,
PDO::ATTR_PERSISTENT => FALSE,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
]
);
Create table syntax
CREATE TABLE `kunden` (
`kunde_id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`nachname` varchar(100) DEFAULT NULL,
`vorname` varchar(255) DEFAULT NULL,
PRIMARY KEY (`kunde_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
Count the rows (results) you fetch form the database.
If the count is zero then display the "no results found" message.
If there are results then take care of displaying the table header before you output the first row.
$count = 0; // This keeps track of the rows fetched
while($ds = $sql->fetch())
{
// Before the first row let's put the table header
if( $count === 0 )
{
echo "<table>";
echo '<p class="abfrage2">Abfrage 3:</p>';
echo"<tr><th>Nachname</th><th>Vorname</th></tr>";
}
// Output the row
echo "<tr><td>$ds[Nachname]</td><td>$ds[Vorname]</td></tr>";
// Update the row count
$count++;
}
// No rows/results? display the message
// Otherwise close the table
if( $count === 0 )
{
// Display "no matches" message ex:
echo "<div class='some-class'>Sorry, but none of your letters match with the Names in the database</div>";
}
else
{
echo "</table>";
}
Note that your code is unsafe as prone to sql injection.
Use Prepared Statements to inject user data into the query.
When you take user input and put it into a query after a LIKE statement then % wildcards must be escaped in the input string. See this question an the accepted answer.
Finally you should trim() $kundevor and $kundenach before using them; make sure to close the <table> html at some point, I put the code after the while loop. You have some fixes to take care of...
Related
I have an assignment in which needs to be corrected. My code has all working functionality. However, I need my code to be able to display my reservations table when the page is initially opened and loaded. Currently, the table is only shown when another flight is added. I believe I am missing a few lines of code or am not putting the code in the correct section. Please help.
> <html>
<head>
<title>HW09</title>
</head>
<body>
<h1>HW09 - Airline Reservation</h1>
<form>
<h3>Find a flight:</h3>
<?php
include("config.php");
$connect=mysqli_connect("localhost",$username,$dbpassword,"CHA") or die ("Cannot open database");
$sql="SELECT * FROM `AirportList` ";
$result = mysqli_query($connect,$sql);
print "<label>From: </label>";
print "<select name='from'>";
while ($row = $result -> fetch_assoc()) {
print "<option value='" . $row['AirportCode'] . "'>" . $row['AirportName'] . "</option>\n";
}
print "</select>\n";
print "<br>";
$result = mysqli_query($connect,$sql);
print "<label>To: </label>";
print "<select name='to'>";
while ($row = $result -> fetch_assoc()) {
print "<option value='" . $row['AirportCode'] . "'>" . $row['AirportName'] . "</option>\n";
}
print "</select>\n";
print "<br>";
print "<label>Date: </label>";
print "<input type=\"date\" name=\"datee\" id=\"datee\" >";
print"<br>
<input type='submit' value='Find Flights'>
</br>";
$de = $_GET['datee'];
$d = str_replace("-","",$de);
$from = $_GET['from'];
$to = $_GET['to'];
$sql2 = "SELECT * FROM `Flights` WHERE `Date` LIKE '$d' AND `Takeoff` LIKE '$from' AND `Landing` LIKE '$to' ";
print "<br />";
if ($_GET) {
print "<p>Let's find a reservation</p>";
$result2 = mysqli_query($connect,$sql2);
$count = 0;
while ($num = $result2 -> fetch_assoc()) {
$count = $count + 1;
}
print "<p>We have " . $count . " options</p><br />";
$result2 = mysqli_query($connect,$sql2);
if ($_GET['datee']) {
print "
<table border=1>
<tr>
<th>Select</th>
<th>Seats</th>
<th>From</th>
<th>To</th>
<th>Time</th>
<th>Flight#</th>
</tr>";
}
while ($info = $result2 -> fetch_assoc()) {
print"
<form>
<tr>
<td>
<input type='hidden' name='addflight' value=" . $info['Serial'] . ">
<input type='submit' name='Reserve' value='Reserve'>
</td>
<td>
<select name='seats'>";
for ($x = 1; $x <= 11; $x++) {
print"<option value= " . $x . ">" . $x . "</option>";
}
print"</td>
<td>" . $info['Takeoff'] . "</td><td>" . $info['Landing'] . "<td>" . $info['Time'] . "</td><td>" . $info['Flightnum'] . "</td></tr>
</form>";
}
print "</table>";
if (isset($_GET['Reserve'])) {
$connect3=mysqli_connect("localhost",$username,$dbpassword,"jasonlalaki_HW09") or die ("Cannot open database");
$sql3="INSERT INTO `Reservations` (`ResSerial`, `Seats`) VALUES (" . $_GET['addflight'] . ", " . $_GET['seats'] . ");";
$result3 = mysqli_query($connect3,$sql3);
$sql4="SELECT * FROM `Reservations` ";
$result4 = mysqli_query($connect3,$sql4);
print"
<table border=1>
<tr>
<th>Delete</th>
<th>Date</th>
<th>Time</th>
<th>Flight</th>
<th>From</th>
<th>To</th>
<th>Seats</th>
</tr>";
while ($row1 = $result4 -> fetch_assoc()) {
$sql5="SELECT * FROM `Flights` WHERE `Serial` = " . $row1['ResSerial'];
$result5 = mysqli_query($connect,$sql5);
while ($info2 = $result5 -> fetch_assoc()) {
print"
<form>
<tr>
<td>
<input type='submit' name='Delete' value='Delete'>
</td>
<td>" . $info2['Date'] . "</td><td>" . $info2['Time'] . "</td><td>" . $info2['Flightnum'] . "</td><td>" . $info2['Takeoff'] . "</td><td>" . $info2['Landing'] . "</td><td style=\"text-align: right;\">" . $row1['Seats'] . "</td></tr>
</form>";
}
}
print"
</table>";
}
}
?>
</form>
</body></html>
After studying your code a bit, I decided to rewrite it - including the naming conventions of the tables, to show you a "best practice" example. The table structures chosen by me are certainly not the correct ones, but I didn't consider this here of big relevance.
Suggestions:
You should always avoid printing HTML code using PHP code. For example, avoid snippets like this: print "<label>From: </label>";. Write HTML code as normal: <label>From: </label>.
There are the cases where PHP code must be printed inside HTML controls (values, attributes, etc). Then try to print only PHP variables, no complex code. Instead of <input value="<?php echo $selectedFlightDate ?? ''; ?>" ... /> optimize to <?php $defaultFlightDate = $selectedFlightDate ?? ''; ?> <input value="<?php echo $defaultFlightDate; ?>" ... />.
Try to separate the database querying PHP codes from the rest of the page. The querying results should be fetched in arrays, which will easily be used later in the page.
Don't hesitate to use pronounceable and intention-revealing names for variables, constants, functions, etc. So, instead of <input type="date" name="datee"> use <input type="date" name="flightDate">. Or, in PHP, instead of $de = $_GET['datee']; use $flightDate = $_GET['flightDate'];.
You are using MySQLi extension. I suggest you to use the object oriented classes and methods of it, instead of the procedural functions of it. For example, instead of $connection = mysqli_connect(/* args list */); (procedural style) you should use $connection = new mysqli(/* args list */); (object oriented style). See the docs.
You are using MySQLi database extension, but I strongly advice you to switch to the PDO extension as soon as possible!
In order to avoid malicious SQL injections, you should always use the so-called prepared statements. You'll notice that I never used mysqli_query, because it's not compatible with the process of statements preparing. I commented my code a lot, especially where I prepared the SQL statement for fetching the flights list (SELECT * FROM flights WHERE ...).
Code:
Change my db credentials with yours.
I appended the string "_test" to all table names for quickly creating them without affecting yours, and testing.
connection.php:
<?php
/*
* This page contains the code for creating a mysqli connection instance.
*/
// Db configs.
define('HOST', 'localhost');
define('PORT', 3306);
define('DATABASE', 'tests');
define('USERNAME', 'tests');
define('PASSWORD', 'tests');
// Error reporting.
error_reporting(E_ALL);
ini_set('display_errors', 1); /* SET IT TO 0 ON A LIVE SERVER !!! */
/*
* Enable internal report functions. This enables the exception handling.
*
* #link http://php.net/manual/en/class.mysqli-driver.php
* #link http://php.net/manual/en/mysqli-driver.report-mode.php
* #link http://php.net/manual/en/mysqli.constants.php
*/
$mysqliDriver = new mysqli_driver();
$mysqliDriver->report_mode = (MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
// Create a new db connection.
$connection = new mysqli(HOST, USERNAME, PASSWORD, DATABASE, PORT);
index.php:
<?php
require 'connection.php';
/*
* ==================================================================
* Define flags for the various operations. Can be very useful later.
* ==================================================================
*/
$searchingFlightsStarted = false;
$flightReservationStarted = false;
$reservationDeletionStarted = false;
/*
* =========================================================
* Operations upon submission of form "searchingFlightsForm"
* =========================================================
*/
if (isset($_POST['searchFlightsButton'])) {
$searchingFlightsStarted = true;
/*
* Read submitted values.
*/
$selectedStartingAirport = $_POST['startingAirport'] ?? '';
$selectedDestinationAirport = $_POST['destinationAirport'] ?? '';
// I didn't applied any formatting to the date value. Do it, if you need to.
$selectedFlightDate = $_POST['flightDate'] ?? '';
/*
* Validate submitted values.
*/
if (empty($selectedStartingAirport)) {
$errorMessages[] = 'Please select a starting point.';
}
if (empty($selectedDestinationAirport)) {
$errorMessages[] = 'Please select a destination.';
}
if (empty($selectedFlightDate)) {
$errorMessages[] = 'Please select a date for the flight.';
}
/*
* If no validation errors yet, proceed with searching flights.
* Note the use of the prepared statement in order to avoid malicious SQL injections.
*/
if (!isset($errorMessages)) {
/*
* The SQL statement to be prepared. Notice the so-called markers,
* e.g. the "?" signs. They will be replaced later with the
* corresponding values when using mysqli_stmt::bind_param.
*
* #link http://php.net/manual/en/mysqli.prepare.php
*/
$sql = 'SELECT *
FROM flights_test
WHERE
date = ? AND
takeoff LIKE ? AND
landing LIKE ?';
/**
* Prepare the SQL statement for execution, but
* ONLY ONCE - read the docs to find out why.
*
* #link http://php.net/manual/en/mysqli.prepare.php
*/
$statement = $connection->prepare($sql);
$boundSelectedStartingAirport = '%' . $selectedStartingAirport . '%';
$boundSelectedDestinationAirport = '%' . $selectedDestinationAirport . '%';
/*
* Bind variables for the parameter markers ("?") in the
* SQL statement that was passed to prepare(). The first
* argument of bind_param() is a string that contains one
* or more characters which specify the types of the
* corresponding bind variables (string, integer, etc).
*
* #link http://php.net/manual/en/mysqli-stmt.bind-param.php
*/
$statement->bind_param(
'sss',
$selectedFlightDate,
$boundSelectedStartingAirport,
$boundSelectedDestinationAirport
);
/*
* Execute the prepared SQL statement.
* When executed any parameter markers which exist,
* e.g. each "?" character, will automatically be
* replaced with the appropriate data.
*
* #link http://php.net/manual/en/mysqli-stmt.execute.php
*/
$statement->execute();
/*
* Get the result set from the prepared statement.
*
* NOTA BENE:
* Available only with mysqlnd ("MySQL Native Driver")! If this
* is not installed, uncomment "extension=php_mysqli_mysqlnd.dll" in
* php.ini and restart web server and mysql service. Or use the following instead:
* mysqli_stmt::store_result + mysqli_stmt::bind_result + mysqli_stmt::fetch.
*
* #link http://php.net/manual/en/mysqli-stmt.get-result.php
* #link https://stackoverflow.com/questions/8321096/call-to-undefined-method-mysqli-stmtget-result
*/
$result = $statement->get_result();
// Fetch all found flights and save them in an array for later use.
$foundFlights = $result->fetch_all(MYSQLI_ASSOC);
/*
* Free the memory associated with the result. You should
* always free your result when it is not needed anymore.
*
* #link http://php.net/manual/en/mysqli-result.free.php
*/
$result->close();
/*
* Close the prepared statement. It also deallocates the statement handle.
* If the statement has pending or unread results, it cancels them
* so that the next query can be executed.
*
* #link http://php.net/manual/en/mysqli-stmt.close.php
*/
$statement->close();
}
}
/*
* ==========================================================
* Operations upon submission of form "flightReservationForm"
* ==========================================================
*/
if (isset($_POST['reserveFlightButton'])) {
$flightReservationStarted = true;
/*
* Read submitted values.
*/
$flightIdToReserve = $_POST['flightIdToReserve'];
$seatToReserve = $_POST['seatToReserve'];
/*
* Proceed with the reservation of the selected flight.
* Note the use of the prepared statement.
*/
$sql = 'INSERT INTO reservations_test (
flight_id,
seat
) VALUES (
?, ?
)';
$statement = $connection->prepare($sql);
$statement->bind_param('ii', $flightIdToReserve, $seatToReserve);
$statement->execute();
$statement->close();
$successMessages[] = 'The reservation of the selected flight was successfully performed.';
}
/*
* ============================================================
* Operations upon submission of form "reservationDeletionForm"
* ============================================================
*/
if (isset($_POST['deleteReservationButton'])) {
$reservationDeletionStarted = true;
/*
* Read submitted values.
*/
$reservationIdToDelete = $_POST['reservationIdToDelete'];
/*
* Proceed with the deletion of the selected flight.
* Note the use of the prepared statement.
*/
$sql = 'DELETE FROM reservations_test
WHERE id = ?';
$statement = $connection->prepare($sql);
$statement->bind_param('i', $reservationIdToDelete);
$statement->execute();
$statement->close();
$successMessages[] = 'The selected flight reservation was successfully deleted.';
}
/*
* ===========================================================
* Fetch the airports list (used in the searching comboboxes).
* Note the use of the prepared statement.
* ===========================================================
*/
$sql = 'SELECT * FROM airports_test';
$statement = $connection->prepare($sql);
$statement->execute();
$result = $statement->get_result();
// Fetch all airports and save them in an array for later use.
$airports = $result->fetch_all(MYSQLI_ASSOC);
$result->close();
$statement->close();
/*
* =======================================================
* Fetch the reservations list, which is always displayed.
* Note the use of the prepared statement.
* =======================================================
*/
$sql = 'SELECT
r.id,
r.flight_id,
f.date,
f.time,
f.flight_no,
f.takeoff,
f.landing,
r.seat
FROM reservations_test AS r
LEFT JOIN flights_test AS f ON
r.flight_id = f.id';
$statement = $connection->prepare($sql);
$statement->execute();
$result = $statement->get_result();
// Fetch all reservations and save them in an array for later use.
$reservations = $result->fetch_all(MYSQLI_ASSOC);
$result->close();
$statement->close();
?>
<html>
<head>
<!-- Required meta tags -->
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=yes" />
<title>Demo</title>
<link href="styles.css" rel="stylesheet">
</head>
<body>
<header>
<h1>
Airline Reservation
</h1>
</header>
<section class="messages">
<?php
/*
* Display all error messages.
*/
if (isset($errorMessages)) {
foreach ($errorMessages as $errorMessage) {
?>
<div class="error">
<?php echo $errorMessage; ?>
</div>
<?php
}
}
/*
* Display all success messages.
*/
if (isset($successMessages)) {
foreach ($successMessages as $successMessage) {
?>
<div class="success">
<?php echo $successMessage; ?>
</div>
<?php
}
}
?>
</section>
<section>
<header>
<h3>
Search flights:
</h3>
</header>
<article>
<form id="searchingFlightsForm" method="post" action="">
<div class="form-group">
<label>From: </label>
<select name="startingAirport">
<option value="">-- Select a starting point --</option>
<?php
if ($airports) {// if any records available
foreach ($airports as $airport) {
$airportCode = $airport['code'];
$airportName = $airport['name'];
$attributeSelected = ($airportCode === $selectedStartingAirport) ?
'selected' :
'';
?>
<option value="<?php echo $airportCode; ?>" <?php echo $attributeSelected; ?>>
<?php echo $airportName; ?>
</option>
<?php
}
}
?>
</select>
</div>
<div class="form-group">
<label>To: </label>
<select name="destinationAirport">
<option value="">-- Select a destination --</option>
<?php
if ($airports) {// if any records available
foreach ($airports as $airport) {
$airportCode = $airport['code'];
$airportName = $airport['name'];
$attributeSelected = ($airportCode === $selectedDestinationAirport) ?
'selected' :
'';
?>
<option value="<?php echo $airportCode; ?>" <?php echo $attributeSelected; ?>>
<?php echo $airportName; ?>
</option>
<?php
}
}
?>
</select>
</div>
<div class="form-group">
<label>Date: </label>
<?php $defaultFlightDate = $selectedFlightDate ?? ''; ?>
<input type="date" id="flightDate" name="flightDate" value="<?php echo $defaultFlightDate; ?>" />
</div>
<div class="form-group">
<label> </label>
<button type="submit" name="searchFlightsButton" class="formButton" value="Search Flights">
Search Flights
</button>
</div>
</form>
</article>
</section>
<?php
$numberOfFoundFlights = isset($foundFlights) ? count($foundFlights) : 0;
?>
<section>
<header>
<h3>
<?php
$foundFlightsMessage = $numberOfFoundFlights > 0 ?
'Found flights: ' . $numberOfFoundFlights . '. Let\'s make a reservation.' :
'No flights found yet.';
echo $foundFlightsMessage;
?>
</h3>
</header>
<?php
if ($numberOfFoundFlights > 0) {
?>
<article>
<table>
<thead>
<tr>
<th>Select</th>
<th>Seat</th>
<th>From</th>
<th>To</th>
<th>Time</th>
<th>Flight #</th>
</tr>
</thead>
<tbody>
<?php
foreach ($foundFlights as $foundFlight) {
$flightId = $foundFlight['id'];
$flightTakeoff = $foundFlight['takeoff'];
$flightLanding = $foundFlight['landing'];
$flightTime = $foundFlight['time'];
$flightNumber = $foundFlight['flight_no'];
?>
<tr>
<td>
<?php
/*
* You are not allowed to enclose a table row in a "form" tag!
* Though, in HTML5, you can define a form for each table row
* wherever you want on the page, and then add the attribute "form"
* to each control residing outside of it, but destined to belong
* to it. The "form" attribute MUST contain the id of the form
* to which the current control should belong. As example see
* the comboboxes named "seatToReserve" bellow.
*/
?>
<form id="flightReservationForm_<?php echo $flightId; ?>" class="flightReservationForm" method="post" action="">
<input type="hidden" name="flightIdToReserve" value="<?php echo $flightId; ?>">
<button type="submit" name="reserveFlightButton" class="columnButton" value="Reserve">
Reserve
</button>
</form>
</td>
<td>
<select name="seatToReserve" form="flightReservationForm_<?php echo $flightId; ?>">
<?php
for ($seat = 1; $seat <= 11; $seat++) {
?>
<option value="<?php echo $seat; ?>">
<?php echo $seat; ?>
</option>
<?php
}
?>
</select>
</td>
<td><?php echo $flightTakeoff; ?></td>
<td><?php echo $flightLanding; ?></td>
<td><?php echo $flightTime; ?></td>
<td><?php echo $flightNumber; ?></td>
</tr>
<?php
}
?>
</tbody>
</table>
</article>
<?php
}
?>
</section>
<?php
$numberOfReservations = $reservations ? count($reservations) : 0;
?>
<section>
<header>
<h3>
<?php
$reservationsMessage = $numberOfReservations > 0 ?
'Reservations:' :
'No reservations available yet.';
echo $reservationsMessage;
?>
</h3>
</header>
<?php
if ($numberOfReservations > 0) {
?>
<article>
<table>
<thead>
<tr>
<th>Delete</th>
<th>Date</th>
<th>Time</th>
<th>Flight</th>
<th>From</th>
<th>To</th>
<th>Seat</th>
</tr>
</thead>
<tbody>
<?php
foreach ($reservations as $reservation) {
$reservationId = $reservation['id'];
$reservationFlightId = $reservation['flight_id'];
$reservationDate = $reservation['date'];
$reservationTime = $reservation['time'];
$reservationFlightNumber = $reservation['flight_no'];
$reservationTakeoff = $reservation['takeoff'];
$reservationLanding = $reservation['landing'];
$reservationSeat = $reservation['seat'];
?>
<tr>
<td>
<form id="reservationDeletionForm_<?php echo $reservationId; ?>" class="reservationDeletionForm" method="post" action="">
<input type="hidden" name="reservationIdToDelete" value="<?php echo $reservationId; ?>">
<button type="submit" name="deleteReservationButton" class="columnButton" value="Delete">
Delete
</button>
</form>
</td>
<td><?php echo $reservationDate; ?></td>
<td><?php echo $reservationTime; ?></td>
<td><?php echo $reservationFlightNumber; ?></td>
<td><?php echo $reservationTakeoff; ?></td>
<td><?php echo $reservationLanding; ?></td>
<td><?php echo $reservationSeat; ?></td>
</tr>
<?php
}
?>
</tbody>
</table>
</article>
<?php
}
?>
</section>
</body>
</html>
styles.css:
*, *::before, *::after { box-sizing: border-box; }
:root { font-size: 16px; }
body { margin: 0; padding: 20px; font-family: "Verdana", Arial, sans-serif; font-size: 1rem; font-weight: 400; background-color: #fff; }
table { border-collapse: collapse; }
table, th, td { border: 1px solid #ccc; }
th, td { padding: 7px; text-align: left; }
th { background-color: #f4f4f4; }
tbody tr:hover { background: yellow; }
.messages { width: 50%; }
.messages .error { background-color: #e83e8c; color: #fff; padding: 5px; margin: 5px; }
.messages .success { background-color: #5cb85c; color: #fff; padding: 5px; margin: 5px; }
#searchingFlightsForm { width: 50%; padding: 20px; background-color: #f4f4f4; }
#searchingFlightsForm .form-group { padding: 5px; }
#searchingFlightsForm label { display: inline-block; min-width: 70px; }
#searchingFlightsForm select { min-width: 240px; }
#searchingFlightsForm input[type="date"] { min-width: 240px; padding: 7px; }
.formButton { padding: 5px 7px; background-color: #009926; color: #fff; }
.columnButton { padding: 3px 5px; background-color: #0086b3; color: #fff; }
form.flightReservationForm { margin: 0; }
form.reservationDeletionForm { margin: 0; }
The used table definitions and testing data:
"airports_test" table:
CREATE TABLE `airports_test` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`code` varchar(100) DEFAULT NULL,
`name` varchar(100) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8
id|code|name |
--|----|--------------------|
1|LON |London Airport |
2|BUA |Buenos Aires Flights|
3|BUD |Budapest Airport |
"flights_test" table:
CREATE TABLE `flights_test` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`date` varchar(10) DEFAULT NULL,
`time` time DEFAULT NULL,
`takeoff` varchar(100) DEFAULT NULL,
`landing` varchar(100) DEFAULT NULL,
`flight_no` varchar(100) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8
id|date |time |takeoff|landing|flight_no|
--|----------|--------|-------|-------|---------|
1|2020-12-27|15:38:00|BUA |BUD |43245 |
2|2020-12-29|22:44:00|BUD |LON |245 |
3|2020-12-30|05:31:00|BUD |BUA |876643 |
4|2020-12-30|10:00:00|LON |BUD |5443 |
5|2020-12-30|18:45:00|LON |BUD |4287 |
"reservations_test" table:
CREATE TABLE `reservations_test` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`flight_id` bigint(20) unsigned DEFAULT NULL,
`seat` int(10) unsigned DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=12 DEFAULT CHARSET=utf8
id|flight_id|seat|
--|---------|----|
Resources:
(The only proper) PDO tutorial
How to use mysqli properly
PHP error reporting
Clean, high quality code: a guide on how to become a better programmer
I took one of your sql statements and made it a prepaired statement.
You need preparied statements id Mike O'Leary need to fly to O'Heir airport.
<?php
$msi = new mysqli('localhost','misc01','!howTO001','test');
$stmt = $msi->prepare('
Select
*
From
Flights
Where
Date LIKE ? And
Takeoff LIKE ? And
Landing LIKE ?
';
$stmt->bind_param('sss', $d, $from, $to);
$stmt->execute();
$rslt = $stmt->get_result();
echo('<pre>');
print_r($rslt->fetch_all(MYSQLI_ASSOC));
I am just self-learning PHP and SQL. This question seems repetitive, but I cannot find exact solution for my problem.
I have a SQL database for inventory management of mobile phones. I have implemented PHP script to display the database contents in a table. I have to further enhance the script, so the user can change the status of the mobile phone such as Working or Not working. For this I have created another SQL database storing this info. I am able to display the details in a dropdown, but when I change from Working to Not working and select Submit button, no change is seen in the database and also in the web server.
<?php
$servername="localhost";
$username="root";
$password="XXXXX";
$dbname="inventory_db";
//Connection
$conn =mysqli_connect($servername,$username,$password);
$db_handle = $conn->select_db($dbname);
//Connection check
if($conn->connect_error)
{
die("Connection failed:" .$conn->connect_error);
}
else {
echo "connection setup";
}
if($db_handle)
{
$sql="SELECT asset_no,asset_name,current_holder,location,status FROM Phone_table ";
$sql_status="SELECT idstatus,status_name FROM status_table";
?>
<!DOCTYPE html>
<HTML>
<HEAD>
<STYLE>
.asset_table
{
width: 100%;
border :1px solid black;
}
td{
text-align: left;
padding: 15px;
border: 1px solid black;
}
th{
border: 1px solid black;
}
</STYLE>
</HEAD>
<BODY>
<form method="post">
<TABLE class="asset_table">
<TR>
<TH>Asset Number</TH>
<TH>Asset Name</TH>
<TH>Asset Holder</TH>
<TH>Location</TH>
<TH>Status</TH>
</TR>
<?php
$result=$conn->query($sql);
$count=mysqli_num_rows($result);
if($result->num_rows > 0)
{
while($row=$result->fetch_assoc())
{?>
<TR>
<TD> <?php echo $row['asset_no']; ?> </TD>
<TD> <?php echo $row['asset_name']; ?></TD>
<TD> <?php echo $row['current_holder']; ?></TD>
<TD> <?php echo $row['location']; ?></TD>
<TD><select>
<?php
<!-- *****This is where I am stuck*****-->
$result_status=$conn->query($sql_status);
if($result_status->num_rows > 0)
{
while($row_status=$result_status->fetch_assoc())
{ ?>
<option value =' <?php echo $row_status['idstatus']?> '>
<?php echo $row_status['status_name'];?> </option>
<?php $row['status']=$row_status['status_name'];
}} ?></select>
</TD>
</TR>
<?php
}}?>
<input type="submit">
</form>
<?php
if($submit)
{
for($i=0;$i<$count;$i++)
{
$sql="UPDATE Phone_table SET status='$status[$i]' WHERE asset_no='$asset_no[$i]'";
$result=$conn->query($sql);
}
}
?>
</TABLE>
</BODY>
</HTML>
<?php }
ob_end_flush(); ?>
One problem with the existing code is that there was no way to relate the submitted value for the asset status ( even if it had been given a name! ) to the particular record in the database. The update statement would require, usually, an ID in the where clause so that the releveant record can be updated as opposed to ALL records being updated equally. To that end, given the HTML structure and generaly approach ( no javascript & single form ) using a hidden input field for each row in the table to hold the record ID seems to make sense. When the form is submitted the value for the select menu and the id should be relatable - you will see by the demo below.
Because there is a single form with multiple records the select menu and the hidden input will need to be treatable as arrays - that is to say their names should be of the form name[]
Another thing to note perhaps is the use of variables directly within the sql. This practise leaves your code vulnerable to sql injection and whilst this may be on a closed system somewhere with trusted users etc you never know what might happen!
<?php
error_reporting( E_ALL );
ini_set( 'display_errors', 1 );
/* connect to the db */
$dbhost = 'localhost';
$dbuser = 'root';
$dbpwd = 'xxx';
$dbname = 'inventory_db';
$db = new mysqli( $dbhost, $dbuser, $dbpwd, $dbname );
/* declare the sql statements for later use */
$sql=(object)array(
'phones' => 'select `asset_no`, `asset_name`, `current_holder`, `location`, `status` from `phone_table`',
'status' => 'select `idstatus`, `status_name` from `status_table`',
'update' => 'update `phone_table` set `status`=? where asset_no=?'
);
/* very basic utility function to generate select menu */
function createselect( $name, $data, $value ){
$html=array();
$html[]=sprintf( '<select name="%s">', $name );
foreach( $data as $id => $status ){
$selected = $id == $value ? ' selected=true' : '';
$html[]=sprintf('<option value="%s"%s>%s', $id, $selected, $status );
}
$html[]='</select>';
return implode( PHP_EOL, $html );
}
/* query database to get possible status values which are used to create the SELECT menus */
$status=array();
$results=$db->query( $sql->status );
if( $results ){
while( $rs=$results->fetch_object() )$status[ $rs->idstatus ]=$rs->status_name;
}
if( $_SERVER['REQUEST_METHOD']=='POST' ){
ob_clean();
/* using `user supplied data` - use a prepared statement to be safe! */
$stmt=$db->prepare( $sql->update );
$stmt->bind_param( 'ii', $assetstatus, $assetid );
/* Perform the update */
foreach( $_POST['id'] as $i => $assetid ){
$assetstatus = $_POST['status'][ $i ];
$stmt->execute();
}
$stmt->close();
exit( header( 'Location: ?db=updated' ) );
}
?>
<!DOCTYPE html>
<html lang='en'>
<head>
<meta charset='utf-8' />
<title>Asses or Assets?</title>
<style>
body{font-family:verdana}
table{ width: 100%; border :1px solid black; }
td{ text-align: left; padding: 15px; border: 1px solid black;text-align:center; }
th{ border: 1px solid black; }
input,select{padding:1rem;width:100%}
</style>
</head>
<body>
<?php
/* get the phones... no user input so no need for prepared statement */
$results = $db->query( $sql->phones );
if( $results ){
?>
<form method='post'>
<table>
<thead>
<tr>
<th>Asset Number</th>
<th>Asset Name</th>
<th>Asset Holder</th>
<th>Location</th>
<th>Status</th>
</tr>
</thead>
<tbody>
<?php
while( $rs = $results->fetch_object() ){
printf(
"<tr>
<td>%s<input type='hidden' name='id[]' value='%d' /></td>
<td>%s</td>
<td>%s</td>
<td>%s</td>
<td>%s</td>
</tr>",
$rs->asset_no,
$rs->asset_no,
$rs->asset_name,
$rs->current_holder,
$rs->location,
createselect( 'status[]', $status, $rs->status )
);
}
?>
</tbody>
<tfoot>
<tr>
<td colspan=5>
<input type='submit' />
</td>
</tr>
</tfoot>
</table>
</form>
<?php
}//close `if`
?>
</body>
</html>
In general the form creation/display and the acting upon the submitted form are two entirely unrelated HTTP requests.
You have to change a few things to get your script to work:
1. Add a hidden field for each asset no.:
<TD>
<input type="hidden" name="asset_no[]" value="<?php echo $row['asset_no']; ?>">
<?php echo $row['asset_no']; ?>
</TD>
2. Add name attribute to your select fields:
<TD><select name="asset_status[]">
3. Make your select fields preselect the current status and remove the whitespace in the value:
<option value ='<?php echo $row_status['idstatus'] ?>' <?= $row['status'] == $row_status['idstatus'] ? ' selected' : '' ?>>
4. Remove this statement, as it does nothing (you're not writing to the array you read from the database):
$row['status']=$row_status['status_name'];
5. Add a name property to your submit field:
<input type="submit" name="submit">
6. Read your submitted form from the superglobal array $_POST (see php.net):
if(isset($_POST['submit']))
{
for($i=0;$i<count($_POST['asset_no']);$i++)
{
$asset_status = mysqli_real_escape_string($conn, $_POST['asset_status'][$i]);
$asset_no = mysqli_real_escape_string($conn, $_POST['asset_no'][$i]);
$sql = "UPDATE Phone_table SET status='$asset_status' WHERE asset_no='$asset_no'";
$result = $conn->query($sql);
}
}
I can't seem to get $_POST to work with my sql query. I have tried both mysql_query and PDO.
$newartist = $_POST['newartist']; // This doesn't work with PDO statement
//$newartist = 'Hubert De Lartigue'; // This works with PDO statement!
//$query = $DBH->prepare("SELECT * FROM artist WHERE artist =?"); // Original Method
//$query->bindValue(1, $newartist, PDO::PARAM_STR); // Original Method
$query = $DBH->prepare("SELECT * FROM artist WHERE artist = :newartist"); // Suggested Method
//$query->bindParam(':newartist', $newartist); // Suggested method, tested
$query->bindParam(':newartist', $newartist, PDO::PARAM_STR); // Suggested method
$query->execute();
//foreach ($query as $row) { // Switched to while loop so it can "fetch"
while ($row = $query->fetch(PDO::FETCH_ASSOC)) {
$selectedartist = '<option value="'.$row['artist_id'].'" selected="selected">'.$row['artist'].'</option>';
}
I can however echo $_POST['newartist']; and it will correctly output the artist's name!
The form per request (NOTE: you have to click the + to submit an artist and newartist echos properly after submitting a new artist):
<div style="background: #270126; padding: 0 20px;" id="artist" >
<form method="post" style="width: 100%">
Artist: <select name="artist" style="width: 200px; background: black;" class="required">
<?php
if(!empty($_POST['newartist'])) {
echo $selectedartist;
} else {
echo '<option value="2" selected="selected">Unknown-Artist</option>
'.$theartist.'';
}
?></select> +</div>
<div style="background: #270126; padding: 0 20px;" id="addnewartist" >
<fieldset style="display: none;height: 35px;" id="artistnew">
Artist Name:
<input name="newartist" id="newartist" style="width: 200px; display:inline;" /> Artist URL:<input name="artist_url" value="http://" />
<input type="submit" value="Submit New Artist" name="addartist" class="secondaryAction" style="display:inline;" />
</fieldset>
</div>
<fieldset id="artworknew" style="width: 100%;">
<div style="background: #270126; padding: 0 20px;">
Artwork Name: <input name="name" id="name" style="width: 300px;" />
</div>
<div style="background: #270126; padding: 0 20px;">
File Name: <input name="file" id="file" style="width: 300px" value=".jpg" /><br />
</div>
<div style="background: #270126; padding: 0 20px; height: 35px;">
Folder: <select name="folder" style="width: 200px; background: black;">
<option value="16">digitalart2</option>
<?=$thefolder;?></select>
<input name="disabled" type="checkbox" value="1" />Disable
<input name="dt1" type="hidden" value="<?=date("Y-m-d H:i:s");?>">
</div>
<div align="center">
<input type="submit" value="Submit Artwork" name="addartwork" class="primaryAction" />
</div></fieldset>
</form>
</div>
<?php
if ($_POST['addartist']) {
mysql_query("INSERT INTO `artist` ( `artist_id` , `artist`, `artist_url`)
VALUES (NULL , '".$_POST['newartist']. "', '".$_POST['artist_url']. "');") or die(mysql_error());
//echo '<meta http-equiv="refresh" content="0;url=?form=addart">';
}
if ($_POST['addartwork']) {
// list($subcategory, $subcategory_id, $type, $link, $width, $height) = split(":", $_POST['subcategory']);
// list($genre, $genre_id) = split(":", $_POST['genre']);
mysql_query("INSERT INTO `artwork` (`id`, `name`, `artist_id`, `file`, `folder_id`, `dt1`, `approved`, `disabled`)
VALUES (NULL ,
'".sql_inj_str($_POST['name'])."',
'".sql_inj_str($_POST['artist'])."',
'".sql_inj_str(htmlentities($_POST['file']))."',
'".sql_inj_str($_POST['folder'])."',
'".sql_inj_str($_POST['dt1'])."',
'1',
'".sql_inj_str($_POST['disabled'])."');
") or die(mysql_error());
//$qu=mysql_query("SELECT LAST_INSERT_ID() INTO #artwork;");
echo '<div align="center" style="margin-top: 25px;">..::[ Artwork Submitted! ]::..</div>';
}
include ('footer.php');
?>
I went through all the code you gave me. You have many bad html, css and javascript practices. It make your code hard to debug. I have improved your code and maybe if you can follow my logic and comments, you will figure out what's wrong with you code.
Basically, the code you showed me first is perfectly fine. The problem is with your design. You are entering null values for the id column instead of letting the database do it for you. You have a column for an artist_id and inserting in the artist there. Look at your database definitions to make sure that they have the correct structure and are getting the expected variables. Here is you code but made with good practices. If you can follow my code, you will find it easier to debug the problem.
<?php
/** I have re-wrote your code to give you a better way of writing code that makes it easier to debug**/
/**Store input fields as variables so I don't have to repeat certain things**/
$newartist = isset($_POST['newartist']) ? ($_POST['newartist']) : "Unkown Artist"; // either has a value or the value is Unknown Artist. Only has a value if the $_POST is set
$addartist = isset($_POST['addartist']) ? true : false; // the addartist has been posted or not
$addartwork = isset($_POST['addartwork']) ? true : false; // the addartwork has been posted or not
//This is for add new artist
if($addartist){
$newartist = isset($_POST['newartist']) ? $_POST['newartist'] :null;
$newartist = isset($_POST['artist_url']) ? $_POST['artist_url'] :null;
/**when you do new entry into a database, the primary key or the id field should be left alone,
it automatically updates itself. You must have a primary key in your database for things to work out properly**/
mysql_query("INSERT INTO `artist` ( `artist`, `artist_url`)
VALUES ('". $newartist . "', '". $artist_url . "');") or die(mysql_error());
}else{
$newartist = null;
$artist_url = null;
}
/// this is for adding artwork
if($addartwork){
$name = isset($_POST['name']) ? $_POST['name'] :null;
$artist = isset($_POST['artist']) ? $_POST['artist'] :null;
$file = isset($_POST['file']) ? htmlentities($_POST['file']) :null;
$folder = isset($_POST['folder']) ? $_POST['folder'] :null;
$dt1 = isset($_POST['dt1']) ? $_POST['dt1'] :null;
$disabled = isset($_POST['disabled']) ? 1 : 0;
// list($subcategory, $subcategory_id, $type, $link, $width, $height) = split(":", $_POST['subcategory']);
// list($genre, $genre_id) = split(":", $_POST['genre']);
/**when you do new entry into a database, the primary key or the id field should be left alone,
it automatically updates itself. You must have a primary key in your database for things to work out properly**/
//There is a problem with you artist_id column. The artist has a string value, and you have an id column in the database
//Also you have a sql_inj_str() function. I am guessing that you have difined this function somewhere.
mysql_query("INSERT INTO `artwork` ( `name`, `artist_id`, `file`, `folder_id`, `dt1`, `approved`, `disabled`)
VALUES (NULL ,
'".sql_inj_str($name)."',
'".sql_inj_str($artist)."',
'".sql_inj_str(htmlentities($file))."',
'".sql_inj_str($folder)."',
'".sql_inj_str($dt1)."',
'1',
'".sql_inj_str($disabled)."');
") or die(mysql_error());
//$qu=mysql_query("SELECT LAST_INSERT_ID() INTO #artwork;");
echo '<div align="center" style="margin-top: 25px;">..::[ Artwork Submitted! ]::..</div>';
}else{
$name = null;
$artist = null;
$file = null;
$folder = null;
$dt1 = null;
$disabled = 0;
}
?>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Database Query PDO</title>
<!-- Put the styles (CSS) seperate from the html, easier to maintain. You can just copy these styles into an external file and just link it-->
<style>
#artist {
/**background: #270126;**/
/** I just used a different color from yours so that I can see, design choice**/
background: linen;
padding: 0 20px;
}
/** give the tag in the html a class name or id in the html and replace the tag name here with the class or id given **/
form {
width: 100%;
}
/** give the tag in the html a class name or id in the html and replace the tag name here with the class or id given **/
select {
width: 200px;
/**background: black;**/
/** I just used a different color from yours so that I can see, design choice**/
background: linen;
}
/** give the tag in the html a class name or id in the html and replace the tag name here with the class or id given **/
a {
width: 15px;
font-size: 1.5em;
display:inline;
/**added a myself**/
text-decoration: none;
}
#addnewartist{
/**background: #270126;**/
/** I just used a different color from yours so that I can see, design choice**/
background: linen;
padding: 0 20px;
}
fieldset#artistnew{
display: none;
height: 35px;
}
form #newartist {
width: 200px;
display:inline;
}
form .secondaryAction{
display:inline;
}
#artworknew{
width: 100%;
}
/** I now had no choice but to add in a few class names here**/
.ArtworkName{
/**background: #270126;**/
/** I just used a different color from yours so that I can see, design choice**/
background: linen;
padding: 0 20px;
}
input[name='name'] {
width: 300px;
}
.FileName{
/**background: #270126;**/
/** I just used a different color from yours so that I can see, design choice**/
background: linen;
padding: 0 20px;
}
input[name='file'] {
width: 300px;
}
.Folder {
/**background: #270126;**/
/** I just used a different color from yours so that I can see, design choice**/
background: linen;
padding: 0 20px;
height: 35px;
}
select[name='folder'] {
width: 200px;
/**background: #270126;**/
/** I just used a different color from yours so that I can see, design choice**/
background: linen;
}
</style>
</head>
<body>
<form method="post">
<!-- move the div inside the form-->
<div id="artist" >
Artist:
<select name="artist" class="required">
<?php echo '<option value="' . $newartist . '" selected="selected">' . $newartist . '</option>'; ?>
</select>
<!--When the link is clicked it runs the doStyles function-->
+
<!-- get all the javascript out of the anchor tag. You can use jquery or external javscript but doing it this way is really really bad practice-->
<script>
// You can store this code in an external javscript file and embed it here
function doStyles(){
document.getElementById('artistnew').style.display='block';
document.getElementById('artworknew').style.display='none';
document.getElementById('artist').style.display='none';
}
</script>
</div>
<div id="addnewartist" >
<fieldset id="artistnew">
Artist Name:
<input name="newartist" id="newartist" />
Artist URL:
<input name="artist_url" value="http://" />
<input type="submit" value="Submit New Artist" name="addartist" class="secondaryAction" />
</fieldset>
</div>
<fieldset id="artworknew" >
<div class="ArtworkName">
Artwork Name:
<input name="name" id="name" />
</div>
<div class="FileName">
File Name:
<input name="file" id="file" value=".jpg" /><br />
</div>
<div class="Folder">
Folder:
<select name="folder" >
<option value="16">digitalart2</option>
<?=$thefolder;?>
</select>
<input name="disabled" type="checkbox" value="1" />Disable
<input name="dt1" type="hidden" value="<?=date("Y-m-d H:i:s");?>">
</div>
<div align="center">
<input type="submit" value="Submit Artwork" name="addartwork" class="primaryAction" />
</div>
</fieldset>
</form>
</div>
</body>
</html>
Everything looks OK. Check you form again, and make sure the name attribute is correct. Also, if you are typing in the name on the search form, make sure you are taking care of the case sensitive. The name should match the name in the database.
Use bindParam
Try taking out the PDO::PARAM_STR for now.
Lastly try this:
$result = $query->execute();
and then use $result in the for each loop
I have a form that I would like to have display two versions of the data. I know that I can set two variables for this, but I can't figure out how to get it to insert into the postgres db. I have gotten as far populating the data and having the labels to enter in the new numbers for insertion into the table.
Here's what I have so far ...
<script>
window.onload = function() {
<?
$yesterday = date('Y-m-d', strtotime('-1 day'));
if ($_REQUEST['start'] == '') {
$_REQUEST['stores'] = array(1,2,3,7,8,9,17,18,19,23,16,11,4,5,6);
$_REQUEST['start'] = $yesterday;
} else {
$_REQUEST['stores'] = array(1,2,3,7,8,9,17,18,19,23,16,11,4,5,6);
}
$_REQUEST['submit'] = 'Get Data';
?>
}
</script>
<?
// various arrays and db connections we're going to need later
include('/home/...some_data_goes_here.../db_connect.inc');
$dbx = DB::connect('******');
$dbx->setFetchMode(DB_FETCHMODE_ASSOC);
//get the data based on the date.
$start = $_REQUEST['start'];
//$stores = array(1 => '1,177,18', 2 => '2,277,28', 3 => '3,377,38', 7 => '4,477,48', 8 => '5,577,58', 18 => '338', 19 => '50,51', 9 => '6,677,68', 17 => '8,877,818', 16 => '44,45,47', 11 => '7,770,78', 4 => '11,15,17', 5 => '22,25,27', 6 => '33,35,37');
$formstores = $_REQUEST['stores'];
foreach($stores as $sid => $pcs) {
$store_name = $db->getOne('SELECT store_name FROM stores WHERE store_id = ?', array($sid));
}
foreach($formstores as $k => $sid) {
if(empty($storeDataMain)){ //array is empty so make one
$storeDataMain = array();
}
//get the store names
$store_name = $db->getOne('SELECT store_name FROM stores WHERE store_id = ?', array($sid));
if(DB::isError($store_name)) { echo '<div class="error">Error '.$store_name->getdebuginfo().'</div>'; return; }
$tempups = $db->getOne('SELECT sum(count) FROM traffic WHERE store_id = ? AND tdate = ?', array($sid,$start));
//echo $tempups .' | ';
if(DB::isError($tempups)) { echo '<div class="error">Error '.$tempups->getdebuginfo().'</div>'; return; }
$tups = $tempups/2;
//echo $tups;
//Build array out and return it
$storeDataMain[$store_name] = array('trafficGuests' => number_format(floatval($tups),1,'.',',')); // floatval prevents the numbers from rounding to zero
}
?>
<h3 class="heading">Traffic Updates</h3>
<p>Enter dates in yyyy-mm-dd format.</p>
<script type="text/javascript" src="/css/prototype.js"></script>
<script type="text/javascript" src="/css/scriptaculous.js"></script>
<script type="text/javascript" src="/css/datepicker.js"></script>
<form name="setTraffic" method="get" action="/traffic/updateTraffic.php">
<!-- Build the table where they can input the date to be changed -->
<table>
<tr>
<th>Date</th>
</tr>
<tr>
<td>
<input type="text" name="start" id="start" value="<?=$_REQUEST['start']?>" alt="mm/dd/yyyy" onblur="if(this.value.length){valid=check_date(this.value);if(!valid){this.value='';this.focus();alert('Invalid date input');}else{this.value=valid;}}" onchange="if(this.value.length){valid=check_date(this.value);if(!valid){this.value='';this.focus();alert('Invalid date input');}else{this.value=valid;}}" onfocus="if(this.value == this.defaultValue) this.value = ''" /></td>
<script type="text/javascript">
var start_picker = new DatePicker({
relative : 'start',
language : 'en',
dateFormat : 'yyyy-mm-dd',
showDuration: 0.1,
closeEffectDuraction: 0.1,
disableFutureDate: true,
disablePastDate: false,
keepFieldEmpty : true
});
</script>
</td>
</tr>
</table>
<input class="button" type="submit" name="submit" value="Get Data" id="submit" />
</form>
<form method="post" action="">
<table>
<tr>
<th style="height: 20px; width: 165px; vertical-align: bottom;">Stores</th>
<? //build the list of stores for the headers.
foreach($storeDataMain as $k => $val){
echo '<th style="text-align: center; vertical-align: bottom;">'.$k.'</th>';
}
?>
</tr>
<tr>
<th style="height: 20px; vertical-align: bottom;">Guests for <?=$start?> </th>
<? //format and print out the traffic for each store
foreach($storeDataMain as $k => $val){
echo '<td style="text-align: center; vertical-align: bottom; font-size: 14px;">'.$val["trafficGuests"].'</td>';
}
?>
</tr>
<tr>
<th style="height: 20px; vertical-align: bottom;">Adjustment for <?=$start?></th>
<? //build the input fields identified based on store id.
foreach($formstores as $pcs) {
echo '<td><input class="newTraffic" type="number" style="width: 65px; text-align: right;" name="new_count" id="'.$pcs.'" value="'.$count.'" />'.$count.'</td>';
<script>// get the data ready for inserting into the database
if(isset($count)){
$count = $_POST['']
} else {
$count = '';
}}
if( $_POST ){
$count = $_POST["count"];
$store_id = $sid
$insertCounts = $db->query('INSERT INTO traffic (store_id, thour, tdate, count, door) VALUES ('$sid', )');
}
}
</script>
}
?>
</tr>
</table>
<input class="button" type="submit" name="submit2" value="Submit" id="submit" />
</form>
<h5 style="color: #707070;">New Traffic Counts</h5>
<table style="color: #707070;">
<tr>
<td style="height: 20px; width: 165px; font-weight: bold; vertical-align: bottom;">Stores</td>
<? //display the list of stores for the output of the new counts.
foreach($storeDataMain as $k => $val){
echo '<td style="text-align: center; width: 69px; padding: 4px; font-weight: bold; vertical-align: bottom;">'.$k.'</td>';
}
?>
</tr>
<tr>
<td style="height: 20px; vertical-align: bottom; font-weight: bold;">Guests for <?=$start?></td>
<? //format and display the NEW traffic for each store
foreach($storeDataMain as $k => $val){
$newCount = $val["trafficGuests"] + $count[$pcs];
echo '<td style="text-align: center; vertical-align: bottom; font-size: 14px;">'.$newCount.'</td>';
}
?>
</tr>
</table>
</form>
If you'd like to see what the page looks like you can go [here] (https://picasaweb.google.com/105736785937866961668/January22013#5828892865441021874) and the inputs are designed to take in the adjustment to the number, whether it's positive or negative. From there it is inserted into the DB table and added to the existing sum so that the new total can be reflected in the bottom greyed out table.
I know that this is something that may not be able to be accomplished, but if it can't I need to be able to get to the point where my data will still be entered into the table and then reflected after submit. I just can't seem to get there with my existing knowledge of code.
Please help?!
I can't comment on a question yet, but I think there are a few issues with your php. as #Anubis points out the insert statement needs work. Also, the first few lines of actual php code look like they are wrapped in a javascript event for the window loading. This is not needed as the code doesn't produce any javascript to run. This code will be run on the server during every page load anyway. There are a few other places you have <script> tags that are not needed and probably cause some errors.
I think what you want is to do is add an identifier to your post fields to help get the correct values. So when you are building your input boxes do it like this:
echo '<td><input class="newTraffic" type="number" style="width: 65px; text-align: right;" name="new_count__'.$pcs.'" id="'.$pcs.'" value="'.$count.'" />'.$count.'</td>';
And access the submitted values as follows: $_POST['new_count__' . $pcs]
You are trying to integrate two separate processes which makes your code hard to follow and more error prone. I see what you are trying to do but try putting input processing code at the top and display code towards the bottom. So in rough code/comments:
<?php //check for and process the new data
//if posted values
//process $_POST for values to add/subtract
//if(isset($_POST)) {
//if(!empty($_POST) {
switch ($_POST['submit']) {
case 'submit':
//new date selected
//get new display data
break;
case 'submit2':
//new traffic counts submitted
//for each input submitted
//add/subtract value to current database traffic value
//get new display data
break;
default:
//stuff if no submit
//get default display data
}
?>
<html>
display html data here
</html>
Your insert statement is wrong:
//, thour, tdate, count, door <- are there default values defined for theses? if not set the values
$db->query('INSERT INTO traffic (store_id) VALUES ('.$sid.')');
while programming you should use this error settings:
error_reporting(E_ALL | E_STRICT);
ini_set('display_errors', 1);
this gives you lots of errors and descriptions when something goes wrong and it makes debugging easier.
in a production environment "display_errors" should be 0!
Currently i have a working PHP edit script, which allows users to edit ads they have posted, but I have realized that users can modify the ?id= number to bring up another set of data then edit someone else data and save it in the database.
Is there any way I can make it so that when the user clicks on their advert they have posted to edit, it is only their own ads that they access to, that they wont be able to edit other peoples ads by adjusting the id?= and a way of protecting the form from manipulation?
Here is my current code:
<?php
/*
EDIT.PHP
Allows user to edit specific entry in database
*/
// creates the edit record form
// since this form is used multiple times in this file, I have made it a function that is easily reusable
function renderForm($id, $fname, $lname, $contact, $price, $error)
{
?>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<title>Edit Record</title>
<link rel="stylesheet" type="text/css" href="stylesheet.css">
<style type="text/css">
#page-wrap {
position:absolute;
top: 206px;
left: 288px;
width: 50%;
text-align:left;
background-color:#FFF;
padding: 10px;
border-radius: 10px;
box-shadow: 1px 2px 2px #888888;
}
</style>
<script type = "text/javascript">
function myfunction(url)
{
window.location.href = url;
}
</script>
</head>
<body>
<div class="container">
<div id="imagelogo" onclick = "window.location.href = 'index.html'" >
<p> Buy and sell stuff around University</p>
</div>
<ul id="navigation" name="navigation">
<li id="nav-home">Home</li>
<li id="nav-search">Search</li>
<li id="nav-selling">Selling</li>
<li id="nav-buying">Buying</li>
<li id="nav-FAQ">FAQ</li>
<li id="nav-contact">Contact</li>
<p> </p>
<p> </p>
<p> </p>
<p>Sponsors</p>
</ul>
<div id="account">
<?php
if( isset( $_SESSION['username'] ) ){
echo "<a href='securedpage1.php'>My Account</a><img src='images/uni-icon.png' width='30' height='18' style='vertical-align: middle;'/>";
}else{
echo "<a href='login.php' >Login</a><img src='images/uni-icon.png' width='30' height='18' style='vertical-align: middle;'/>";
}
?>
</div>
<div id="registerlogout">
<?php
if( isset( $_SESSION['username'] ) ){
echo "<a href='logout.php'>Logout</a>";
}else{
echo "<a href='register.php'> Register</a>";
}
?>
</div>
<div id="social">
<img src="images/fb-logo.png" width="22" height="20" />
<img src="images/twitter-logo.png" width="24" height="25" />
</div>
<div id="page-wrap">
<?php
// if there are any errors, display them
if ($error != '')
{
echo '<div style="padding:4px; border:1px solid red; color:red;">'.$error.'</div>';
}
?>
<form action="" method="post">
<input type="hidden" name="id" value="<?php echo $id; ?>"/>
<div>
<strong>Ad Title: *</strong> <input type="text" name="fname" style="width: 60%; box- sizing: border-box; -moz-box-sizing: border-box; -webkit-box-sizing: border-box;"value="<?php echo $fname; ?>"/><br/>
<strong>Description: *</strong> <textarea name="lname" cols="45" rows="5"><?php echo $lname; ?></textarea><br/>
<strong>Contact*</strong> <input type="text" name="contact" style="width: 60%; box- sizing: border-box; -moz-box-sizing: border-box; -webkit-box-sizing: border-box;" value="<?php echo $contact; ?>"/><br/>
<strong>Price*</strong> <input type="text" name="price" style="width: 60%; box-sizing: border-box; -moz-box-sizing: border-box; -webkit-box-sizing: border-box;" value="<?php echo $price; ?>"/><br/>
<p>* Required</p>
<input type="submit" name="submit" value="Submit">
</div>
</form>
</div>
</div>
</body>
</html>
<?php
}
// Inialize session
session_start();
// connect to the database
include('conn.php');
// check if the form has been submitted. If it has, process the form and save it to the database
if (isset($_POST['submit']))
{
// confirm that the 'id' value is a valid integer before getting the form data
if (is_numeric($_POST['id']))
{
// get form data, making sure it is valid
$id = $_POST['id'];
$fname = mysql_real_escape_string(htmlspecialchars($_POST['fname']));
$lname = mysql_real_escape_string(htmlspecialchars($_POST['lname']));
$contact = mysql_real_escape_string(htmlspecialchars($_POST['contact']));
$price = mysql_real_escape_string(htmlspecialchars($_POST['price']));
// check that firstname/lastname fields are both filled in
if ($fname == '' || $lname == '' || $contact == '' || $price == '' )
{
// generate error message
$error = 'ERROR: Please fill in all required fields!';
//error, display form
renderForm($id, $fname, $lname, $contact, $price, $error);
}
else
{
// save the data to the database
mysql_query("UPDATE people SET price='$price', contact='$contact', fname='$fname', lname='$lname' WHERE id='$id'")
or die(mysql_error());
// once saved, redirect back to the view page
header("Location: view.php");
}
}
else
{
// if the 'id' isn't valid, display an error
echo 'Error!';
}
}
else
// if the form hasn't been submitted, get the data from the db and display the form
{
// get the 'id' value from the URL (if it exists), making sure that it is valid (checing that it is numeric/larger than 0)
if (isset($_GET['id']) && is_numeric($_GET['id']) && $_GET['id'] > 0)
{
// query db
$id = $_GET['id'];
$result = mysql_query("SELECT * FROM people WHERE id=$id")
or die(mysql_error());
$row = mysql_fetch_array($result);
// check that the 'id' matches up with a row in the databse
if($row)
{
// get data from db
$fname = $row['fname'];
$lname = $row['lname'];
$contact = $row['contact'];
$price = $row['price'];
// show form
renderForm($id, $fname, $lname, $contact, $price, '');
}
else
// if no match, display result
{
echo "No results!";
}
}
else
// if the 'id' in the URL isn't valid, or if there is no 'id' value, display an error
{
echo 'Error!';
}
}
?>
You need to record, in the database, the poster of each advert. This is just another column.
When an attempt is made to edit an advert (either for displaying the form or saving the result) you need to check that the owner of the advert matches the currently logged in user.
e.g. UPDATE adverts SET text=? WHERE id=? AND user=?
Set a session when they log in. Check if the session-username is the same as the username that is linked to the post they want to edit. If true, they can edit.
I suggest you query the database to check that the id the user is requesting is a id that he/she is allowed to access.
Keep it server side, store the id in a database, and call that number, this will stop them from being able to edit it.
md5 the id number code to each account and add that to the query. Make sure that the code matches the one associated with the account (so md5 the id and make sure it matches the one in the database) then add the stuff. This way no one can change the number and edit other accounts posts. The md5 algorithm is specific to your sever and not predictable.
$hash = md5( $id );
use this to create the code and associate this with the account and use it like the id in addition to the id. This means when you create the account you need to create an md5 version of the id as a field in the database next to the id.
Change this like:
mysql_query("UPDATE people SET price='$price', contact='$contact', fname='$fname', lname='$lname' WHERE id='$id'")
or die(mysql_error());
to
mysql_query("UPDATE people SET price='$price', contact='$contact', fname='$fname', lname='$lname' WHERE id='$id' and idCode='$hash'")
or die(mysql_error());
Just make sure you have a field in the database called idCode because the md5 is an encryption that is not reversible.