Modify $select to allow for searching in php - php

How do I modify my $select function to allow searching with a database when the customer types in the search text and clicks "Search"? I'd also like to be able to type in the form field, and PHP automatically updates the page with the form data dynamically and to be able to define the field to search upon in the database!
This is letting me view my customers table:
$select = $db->query("SELECT * FROM customers ORDER BY id DESC");
<?php
if (!$select->num_rows) {
echo '<p>', 'No records', '</p>';
}else{
?>
<table border="1" width="100%">
<thead>
<tr>
<th>First Name</th>
<th>Last Name</th>
</tr>
</thead>
<tbody>
<?php
while ($row = $select->fetch_object()) {
?>
<tr>
<td><?php echo $row->FName;?></td>
<td><?php echo $row->LName;?></td>

First of all, you might try putting your opening <?php before rather than after the first line of code... :-)
Then you simply modify your code to get the values from your HTML form - I will assume that your search term is named q kind of like this:
Search: <input type="text" name="q" /> <input type="submit" name="search" />
Then your PHP script doing the searching will change the query to something like this:
$select = $db->query("SELECT * FROM customers WHERE FName LIKE '%$_REQUEST[q]%' OR LName LIKE '%$_REQUEST[q]%' ORDER BY id DESC");
If you are entered "Sam" that will end up with a query that looks like this:
$select = $db->query("SELECT * FROM customers WHERE FName LIKE '%Sam%' OR LName LIKE '%Sam%' ORDER BY id DESC");
Do note that I am showing you the simplest version by simply constructing the query. In fact you should NEVER do this with user-supplied data. Instead, you should prepare and then bind and then execute your statement. This is not just filler at the end of the answer - it's really important. But while you are testing you may want to see how it works just be forming a string as above.
To answer your "BONUS POINTS" - you can update the current page by simply including your search form on the same page as the PHP script which displays the results. Then you only process your PHP code if the submit button has been pressed. Your whole script (in a very simple form) might look like this:
Search: <input type="text" name="q" /> <input type="submit" name="search" />
<?php
if (isset($_REQUEST['search'])) {
# do your query
# loop through the results, printing them off in appropriate HTML
}
To answer your "BONUS BONUS" points, you would probably set up a pull-down ("select" in HTML) where the values of the options were the actual field names and the display was a human-readable form of that. If your select had the name "field_name" then you would modify your query like this:
$select = $db->query("SELECT * FROM customers WHERE $_REQUEST[field_name] LIKE '%$_REQUEST[q]%' ORDER BY id DESC");
Do note that you cannot prepare/bind to a column name, so you will just have to be very careful to validate that field very exactly (probably checking that it exists in a list of acceptable values).

Related

PHP/MYSQL - Fetch DB values from dropdown menu, then into table in same page

I'm building an exam management website and one of the pages I'm working on is for adding students to a course. I have a dropdown menu for the student number (which fetches values from a table), however I'd like to make it so that when the teacher selects the student number from the dropdown menu, that student's name and major appear on a table below. I have pretty much all the code for it however I can't seem to make it work. The way it is right now it shows the head of the table but it doesn't show any lines.
The errors are always in the lines where I declare $sql1 and $sql2 and vary according to how I define the condition in the statement.
Code for my dropdown menu : (works fine)
<label class="control-label" for="number">Student Number</label>
<?php
$sql = "SELECT number FROM students";
$result = $conn->query($sql);
echo "<select class=".'"form-control"'.' id="number" name="number" for="number">';
while ($row = $result->fetch_assoc()) {
echo '<option value="' . $row['number'] . '">' . $row['number'] . "</option>";
}
echo "</select>";
?>
Code for my table : (shows only head of table, which is the best I got after moving around the code and getting conversion errors and such)
The errors are always in the lines where I declare $sql1 and $sql2 and vary according to how I define the condition in the statement.
<table class="table">
<thead>
<tr>
<th>Name</th>
<th>Major</th>
</tr>
</thead>
<tbody>
<?php
$sql1 = "SELECT name FROM students WHERE number='$row'";
$result1 = $conn->query($sql1);
$value = $result1->fetch_object();
$sql2 = "SELECT major FROM students where number='$row'";
$result2 = $conn->query($sql2);
$value1 = $result2->fetch_object();
echo "<tr>
<td>".$value."</td>
<td>".$value1."</td>
</tr>";
?>
</tbody>
</table>
Thank you for all your help!!
Before I can formulate a complete answer, I must advise you that there are a few logical errors in your code.
How does your page "know" that a user selected an option from the select? You should perhaps intercept the event and respond to that using an asynchronoys mechanism, e.g. via AJAX.
Anyhow, there's no need to run two queries when you can make it with just one:
SELECT name, major FROM students WHERE number = ...
Once you have described how you mean to address issue #1 we can continue discussing the complete solution.
Well, I think there will be no $row in the the second snippet.
It seems that you didn't pass your $row from 1st snippet to 2nd snippet.
You can read this:
PHP Pass variable to next page
You can use session, cookie, get and post.
Or can just simply use "include", then the variables you defined can be used in the second page.
<?php
include "page1.php";
?>
<table class="table">
<thead>
<tr>
<th>Name</th>
<th>Major</th>
</tr>
</thead>
<tbody>
<?php
$number = $row['number'];
$sql1 = "SELECT name, major FROM students WHERE number='$number'";
$result1 = $conn->query($sql1);
$value = $result1->fetch_object();
echo "<tr>
<td>".$value['name']."</td>
<td>".$value['major']."</td>
</tr>";
?>
</tbody>
</table>
According to godzillante's answer below, the mysql query should be like this:
Anyhow, there's no need to run two queries when you can make it with just one:
SELECT name, major FROM students WHERE number = ...
I notice that you use $row as the key of your second query.
But in the first snippet, the data you fetch is "$row" (it is an array, see PHP - fetch_assoc)
You should use $row['number'] instead.

Retrieving and inserting multiple entries in MySQL/PHP

I'm trying to create a form that retrieves data from a database and then allows me to add data to one column for multiple entries.
Every entry has an ID, a lot of other fields, and a category. I am trying to add these categories for every ID in the database using one form.
I came up with the solution below, but (of course)this only inserts the LAST entry in the form, because the variable ID is changed with every new row.
The form I have now shows me what I want to see, but it does not save it the way I need it to.
The question is, (how) can I make a form that has all entries in the database with a dropdown menu next to it,
lets me select the right category from the dropdown, and save it to the database?
The form:
$result = mysqli_query($con,"SELECT * FROM aw");
while($row = mysqli_fetch_array($result))
{
echo '<tr><td><input type="hidden" name="ID" value="'.$row[ID].'."> '.$row[ID].'</td><td>';
echo '
<select name="cat" onchange="this.form.submit()">
<option value="C1">category1</option>
<option value="C2"">category2</option>
</select></td></tr>
';
}
?>
<tr><td><input type="submit" title="SAVE" ></td></tr>
</form>
The insert.php
$sql="REPLACE INTO aw (ID,cat)
VALUES
('$_POST[ID]','$_POST[cat]')";
if (!mysqli_query($con,$sql))
{
die('Error: ' . mysqli_error($con));
}
mysqli_close($con);
?>
I changed my code according to Tom's answer and I now have the following:
This does print the values like they should be, but it still saves only the last entry into the database. I'm sure I must be missing something here..
$name = $_POST['ID'];
$category = $_POST['cat'];
foreach( $name as $key => $n ) {
$sql="REPLACE INTO aw (ID,cat)
VALUES
('$n','$category[$key]')";
print "The id is ".$n.", category is ".$category[$key]."<br>";
}
First of all, use PDO::Mysql, the SQL functions you are using are a bit deprecated and do not focus much on security. At the moment your code is vulnerable to SQL injections and your output is sensitive to XSS attacks (always sanitize output).
I was wrong, MySQL is deprecated but MySQLi is not! I do prefer using PDO::Mysql because of the range of databases it supports (MySQLi only supports a MySQL database, PDO::Mysql supports many more)
Now to your original question, you can create a sort of array. By making name="ID" to name="ID[]" and name="cat" to name="cat[]".
Now you can do
$name = $_POST['ID'];
$category = $_POST['cat'];
foreach( $name as $key => $n ) {
print "The id is ".$n.", category is ".$category[$key];
}
The problem is your using the name elements regardless of how many rows..
So name="ID" & name="cat" needs to change on each row or have an array type
you could use something like name="ID[]" as this would append/ create an array to $_POST['ID']... but you still would want to change your SQL query to handle each of these.
EDIT
If i understand, you want to be able to identify a row from the table so you can use that in the database?? One way todo this is when creating the table.. Give the TR a id/name attribute that is the row id from the database.
Then can simply know by checking that if your using the select menu from row #4, you check the id/name attribute of the current row and you have your database id.
<tr id='my_row_1'>
<td class='colName'>John</td>
<td class='colPhone'>1111</td>
<td class='colOther'>....</td>
</tr>
<tr id='my_row_2'>
<td class='colName'>Bill</td>
<td class='colPhone'>2222</td>
<td class='colOther'>....</td>
</tr>
<tr id='my_row_3'>
<td class='colName'>Roger</td>
<td class='colPhone'>3333</td>
<td class='colOther'>....</td>
</tr>
With something like the above, Say i had a button in on of the columns... When i click on that button.. all i have todo is find the parent TR and get its id value.... Then explode it by "_" and get the last piece to have the id..
So your PHP would generate the id easily... Also, using a form would not be the best case here.. Using multiple forms within a table is... wasteful... sort of ..
I would suggest more so, having a button that simple calls a js function which will then post/ajax/jquery what you need from that row.
--- Trying to understand exactly what you need??

PHP Updating row in record to yes instead of no but it still shows even though code is for where X = no only

The page is set to show all rows where isthisapproved equals no. This is working how I want by updating isthisapproved to yes. However, after updating isthisapproved from no to yes I don't want it to show anymore... but it is. I'm guessing I have some code in the wrong spot so it isn't "refreshing" the isthisapproved=no query.
<form method='post'>";
$query="SELECT * FROM table WHERE isthisapproved='no'";
$result = mysql_query($query) or die(mysql_error());
$count = mysql_num_rows($result);
echo "<p>$count need approval</p>";
while ($row = mysql_fetch_array($result, MYSQL_ASSOC)) {
$id=$row['id'];
echo "
<table>
<tr>
<td>ID:</td>
<td>$id <input type='hidden' name='id[]' value='$id'></td>
</tr>
<tr>
<td>
<center><input name='submit' type='submit' value='Change To Yes'></form></center>
</td>
</tr>
</table><br>
";}
if($_POST['submit']) {
$update = "UPDATE table SET isthisapproved='yes' WHERE id='$id' LIMIT 1";
if(mysql_query($update)) $count++;
else die("Error in query:<br>$sql<br>");
echo "<p><b>$name approval changed to yes</b></p>";
}
?>
I'd also like to put the notice that the approval worked to be at the top of the page after an update is made instead of at the bottom. I'm not sure how to go about that.
The select query and the update query are using different column names.
$query="SELECT * FROM table WHERE approved='no'";
^^^^^^^^
$update = "UPDATE table SET isthisapproved='yes' WHERE id='$id' LIMIT 1";
^^^^^^^^^^^^^^
Your code is very vulnerable to SQL injection consider using PDO..
Your id is an array so upon submit all of the ids will be sent to your script as it is all contained in one form.
You could wrap it in individual forms and there would also be no need for id to be an array... OR you could place a check box for each user and have the name as id[] then upon submit. you can do this...
foreach($_POST['id'] as $v){
//query goes here. $v is the ID
}
This could however be more efficient and generate a string to be sent as one query to update all users in one go.
First of all you are using "approved" column for select query and "isthisapproved" for update query. So anyway I am assuming it as a typo error. (If not then fix it).
Now pointing out some issue :
Correct your form starting tag and closing tag. Even though it is closing properly. So here form closing tag should be after finishing the table.
After submitting the form you are not receiving the id through $_POST. You are using direct $id which is wrong.
So here you should recieve the id like this and then pass it to update query :
$id = $_POST['id'];

Processing a form created by dynamic php/mySql Setup

I run a script to create an order form, this is just a really small sample. I'm not so good with PHP and dynamic forms. It pulls data from mysql database.
<td>
<h3>Round Cuts</h3>
<?php while($row = mysql_fetch_array($round_cuts)){
$round_box_value = #$row["meat_names"];
$round_box_value_name = #$row["meat_names"];
echo " <input type=\"checkbox\" name=\"round_box_value\" value=\"$round_box_value_name\"> $round_box_value_name";
echo "<br>";
}?>
</td>
I've ever really only built basic contact forms, how could I process a dynamic form like this. If all else fails I would just take all the possible elements and program this like it was a not dynamic. There must be a better way though.
Even a link to a website would be helpful. I've been searching for a solution. Thanks.
I'll assume your table as a primary key of id
Start off with a minor change to your checkboxes:
<?php
while($row = mysql_fetch_array($round_cuts)){
echo sprintf('<label><input type="checkbox" name="round_box_value[]" value="%s"> %s</label><br>', $row['id'], $row['meat_names']);
}
?>
The name now has an [] at the end to tell php it's an array of values + I've wrapped the checkbox in a label for convenience.
Then when you process the form, you can simply iterate through round_box_value like so
<?php
foreach ($_POST['round_box_value'] as $id) {
// $id is the table reference from your previous table
}
// or query all the rows selected
$ids = array_map('intval', $_POST['round_box_value']); // "basic" sql injection handler
$sql = "SELECT * FROM table WHERE id IN (".implode(",", $ids).")";
should produce something like:
SELECT * FROM table WHERE id IN (2,5,7)

PHP form dumps entire MySQL database unless neither input variable exists in the database

I have a form that searches a MySQL database using PHP. Currently, when a user inputs a search into one of two fields, the entire contents of the database are displayed. Also, if the user leaves both fields blank, again, the entire contents of the database will be displayed.
However, if the user inputs random information into both of the fields, then the results page will be blank.
The assumed usage of this form is that the user can search for an article based on the article's title, the article's author or organization, or the article's title and its author or organization by either filling out one or both of the fields.
What I'm trying to figure out is:
Why the results page keeps displaying all of the database contents.
and
How to ensure that the database is actually being queried rather than just being dumped by a coding error.
Code follows below:
search.php:
<div class="content">
<form id="form1" name="form1" method="post" action="searchdb.php">
<table width="100%" border="0" cellpadding="6">
<tr>
<td width="29%" align="right">Article Title:</td>
<td width="71%" align="left"><input name="articletitle" type="text" id="articletitle" size="50" /></td>
</tr>
<tr>
<td align="right">Author or Organization:</td>
<td align="left"><input name="articleorganization" type="text" id="articleorganization" size="50" /></td>
</tr>
</table>
<table width="100%" border="0" cellpadding="6">
<tr>
<td><input type="submit" name="submit" value="Submit" /></td>
</tr>
</table>
</form>
</div>
searchdb.php
<?php
include('settings.php');
$query = "select * from articles";
$where = array();
if (!empty($_POST['articletitle'])) {
$where[] = "articletitle LIKE '%".mysql_real_escape_string($_POST['articletitle'])."%'";
}
if (!empty($_POST['articleorganization'])) {
$where[] = "articleorganization LIKE '%".mysql_real_escape_string($_POST['articleorganization'])."%'";
}
if (!empty($where)) {
$query .= " WHERE " . implode(" OR ", $where);
$sql = mysql_query($query);
} else {
// No results
}
while ($row = mysql_fetch_array($sql)){
echo '<br/> Article Title: '.$row['articletitle'];
echo '<br/> Article Organization: '.$row['articleorganization'];
echo '<td>Edit</td>';
echo '<td>Delete</td>';
echo '<td>View Full Entry</td>';
echo '<br/><br/>';
}
?>
When both are blank, your query states:
WHERE field LIKE '%%'
which matches everything.
The same happens when either one is blank, because you are using an OR to join the where clauses.
You can prevent this from happening, by checking the inputs aren't blank:
<?php
if (!((empty($_POST['field1']) || empty($_POST['field2']))) {
//run your query
}
Following on the post by #sberry.
if (isset($_POST['articletitle']) && $_POST['articletitle'] != "")
The variable can be set, but still be an empty string.
The method used by #xbonez is simpler as
if (!empty($_POST['articletitle'])) is the same as the above example that requires two tests
Have you tried xbonez method?
To be complete, this checks that at least one of the fields has been filled in:
if (!empty($_POST['articletitle']) || !empty($_POST['articleorganization'])) {
$query = "SELECT * from `articles` WHERE ";
$query .= "`articletitle` LIKE '%" . mysql_real_escape_string($_POST['articletitle']) . "%' ";
$query .= "OR `articleorganization` LIKE '%" . mysql_real_escape_string($_POST['articleorganization']) . "%'";
$sql = mysql_query($query);
} else {
// No results
}
Things that will only be used if one of the fields is filled in like:
$query = "SELECT * from `articles` WHERE ";
are placed inside the the if() statement, otherwise they are being parsed unneccesarily.
No need to create an array and then convert it into a string. ".=" will concatenate the string fragments into the final query string.
Matters of personal preference:
MySql keywords written in full caps, I find it makes the statements easier to read.
There are numerous discussions about it.
Search for "sql uppercase keywords style"
Using backticks around table and fieldnames:
Allows the use of reserved keywords for table or fieldnames (count, case, default, div, index, key, limit, option, order, etc...).
Reduces work for the mysql parser, it doesn't need to check whether there is a reserved word conflict.
Avoids problems if your table or field name becomes a reserved keyword in the future.
Again, numerous discussions. Search for "mysql backtick"
MySQLdocumentation:
9.3. Reserved Words
9.2. Schema Object Names
Look for "quoted identifier" on this page.
Also, if you might be migrating to a different database app in the future , you could use double quotes instead of backticks, look for "ANSI_QUOTES".
9.2.4. Function Name Parsing and Resolution
Look for "quoted identifier" on this page.
Tested this, and it should do exactly what you want.
$query = "select * from articles";
$where = array();
if (!empty($_POST['articletitle'])) {
$where[] = "articletitle LIKE '%".mysql_real_escape_string($_POST['articletitle'])."%'";
}
if (!empty($_POST['articleorganization'])) {
$where[] = "articleorganization LIKE '%".mysql_real_escape_string($_POST['articleorganization'])."%'";
}
if (!empty($where)) {
$query .= " WHERE " . implode(" OR ", $where);
$sql = mysql_query($query);
} else {
// No results
}
EDIT
It appears your form is passing empty values, so instead of checking isset, check !empty. I have updated the code above.

Categories