I have a PHP program that allows users to search through an SQL table depending on the input or combination of inputs. I can do single search combination, but can't figure out a way to search by any criteria. What I got so far is terrible because I'm trying to search by every input possibility (and it's not working). This is what I got so far.
<?php
include_once("config.php");
if(isset($_POST['submit'])){
$name = mysqli_real_escape_string($mysqli, $_POST['name']);
$day = mysqli_real_escape_string($mysqli, $_POST['day']);
$month = mysqli_real_escape_string($mysqli, $_POST['month']);
$year = mysqli_real_escape_string($mysqli, $_POST['year']);
// 1 2 3 4
if( !empty($name) && !empty($day) && !empty($month) && !empty($year) ) {
$sql = mysqli_query($mysqli, "SELECT *
FROM transfer
WHERE name like '%$name%'
and day LIKE '%$day%'
AND month LIKE '%$month%'
AND year LIKE '%$year%'");
} else if (!empty($name) && !empty($day) && !empty($month) ) {
$sql = mysqli_query($mysqli, "SELECT *
FROM transfer
WHERE name like '%$name%'
and day LIKE '%$day%'
AND month LIKE '%$month%'");
} else if (!empty($day) && !empty($month) && !empty($year) ) {
$sql = mysqli_query($mysqli, "SELECT *
FROM transfer
WHERE day LIKE '%$day%'
AND month LIKE '%$month%'
AND year LIKE '%$year%'");
} else if (!empty($name && !empty($day) ) {
$sql = mysqli_query($mysqli, "SELECT * FROM transfer
WHERE name like '%$name%' and
day LIKE '%$day%'");
}
//1 3
else if (!empty($name) && !empty($month) )
{
$sql = mysqli_query($mysqli, "SELECT * FROM transfer WHERE name like '%$name%' and month LIKE '%$month%'");
}
//1 4
else if (!empty($name) && !empty($year) )
{
$sql = mysqli_query($mysqli, "SELECT * FROM transfer WHERE name like '%$name%' and year LIKE '%$year%'");
}
//2 3
else if (!empty($day) && !empty($month) )
{
$sql = mysqli_query($mysqli, "SELECT * FROM transfer WHERE day like '%$day%' and month LIKE '%$month%'");
}
//2 3
else if (!empty($day) && !empty($month) )
{
$sql = mysqli_query($mysqli, "SELECT * FROM transfer WHERE day like '%$day%' and month LIKE '%$month%'");
}
//2 4
else if (!empty($day) && !empty($year))
{
$sql = mysqli_query($mysqli, "SELECT * FROM transfer WHERE day like '%$day%' and year LIKE '%$year%'");
}
//3 4
else if (!empty($month) && !empty($year))
{
$sql = mysqli_query($mysqli, "SELECT * FROM transfer WHERE month like '%$month%' and year LIKE '%$year%'");
}
//1
else if (!empty($name))
{
$sql = mysqli_query($mysqli, "SELECT * FROM transfer WHERE name like '%$name%'");
}
//2
else if (!empty($day))
{
$sql = mysqli_query($mysqli, "SELECT * FROM transfer WHERE day like '%$day%'");
}
//3
else if (!empty($month))
{
$sql = mysqli_query($mysqli, "SELECT * FROM transfer WHERE month like '%$month%'");
}
//4
else if(!empty($year))
{
$sql = mysqli_query($mysqli, "SELECT * FROM transfer WHERE year like '%$year%'");
}
else
{
echo "<p>you must insert an input</p>";
}
//while loop used to retrieve data from the SQL database
while ($res = mysqli_fetch_array($sql))
{
echo "<tr>";
echo "<td>".$res['name']."</td>";
echo "<td>".$res['confirmation']."</td>";
echo "<td>".$res['code']."</td>";
echo "<td>".$res['hora']." ".$res['horario']."</td>";
echo "<td>".$res['day']."/".$res['month']."/".$res['year']."</td>";
echo "<td>".$res['extra']."</td>";
echo "</tr>";
}
}
?>
</table>
(Note: It has been said to use prepared statements, which is right - but I don't want to give a copy & paste answer anyway, so here is just an example on how you can achieve your result - use prepared statements anyway. It works the same, except you are creating your query with placeholders and provide the variables that are not empty)
You can create your query in a more "dynamic" way. This is a little tricky, and becomes very "challenging" if joins are required - but what you actually want is to end up with a single query, containing all your constraints.
The first thing, you should define: Are your Searchfields "and" or "or" fields?
if it's "and" it is quite simple to achieve - something like this:
$query = "SELECT * FROM transfer";
$andParts = array();
if(!empty($name))
$andParts[] = "name = '$name'";
if(!empty($day))
$andParts[] = "day = $day";
if (!empty($month))
$andParts[] = "month = $month";
if (!empty($year))
$andParts[] = "year = $year";
if (!empty($andParts))
$query .= " WHERE ".implode(" AND " , $andParts);
$sql->Query($query);
if theres also "or" involved, you'll need another array $orParts, where you first join all the "ors", and finally glue that array together to the final "ands".
If conditions could match columns from "joined" tables, you need to keep track of that, so that you know, from with tables you need to "select".
If you have very complex query for each "searchfield" (i.e. every searchfields result is a result of multiple joins etc...) you can query just the id's for each searchfield, then intersect the results and retrieve the ids matching all criterias:
$result1 = $sql->Query("SELECT id FROM transfer left join .... ");
// array(1,2,3,5,7,10,15,19,27)
$result2 = $sql->Query("SELECT id FROM transfer right join .... ");
// array(2,3,10,15,19,27,43,123)
$result3 = $sql->Query("SELECT id FROM transfer inner join .... ");
// array(2,10,15,27,43,711)
$ids = array_intersect($result1, $result2, $result3);
// array(2,10,15,27)
$finalResult = $sql->Query("SELECT * FROM transfer WHERE id in (".implode(",", $ids).");");
Related
ok, so stay with me here ...
i have a site with a table of about 80,000 rows; i am trying to search this table with one MySQL query. The problem is that each of the fields in the row i'm searching has / might have an array (ex: year = 2017,2016,2015, etc), and some of them may not have anything at all. i have tried doing a loop through to and build my "WHERE" clause as i pull the results, but that isn't working either.
any thoughts? any and all help will be greatly appreciated.
CODE:
INSERT INTO the table - this is one of the 13 different rows
if(!empty($_POST['pd_year']) && is_array($_POST['pd_year'])) {
$pd_year = implode(",", $_POST['pd_year']);
$insert_year = mysqli_query($con, "UPDATE prod_desigs_search_test SET pds_year = '$pd_year' WHERE s_id = '$search'");
} elseif(empty($_POST['pd_year'])) {
$insert_year = mysqli_query($con, "UPDATE prod_desigs_search_test SET pds_year = ' ' WHERE s_id = '$search'");
}
SELECT THE design and check if it is an array or not:
$get_search = mysqli_query($con, "SELECT * FROM prod_desigs_search_test WHERE s_id = '$s_id'");
while($new_search = mysqli_fetch_array($get_search)) {
$pd_year_ex = $new_search['pds_year'];
if(!empty($pd_year_ex) && is_array($pd_year_ex)) {
$pd_year = explode(",", $pd_year_ex, 0);
$year = $pd_year[0];
} elseif(!empty($pd_year_ex) && !is_array($pd_year_ex)) {
$year = $pd_year_ex;
}
$search = mysqli_query($con, "SELECT * FROM prod_designs WHERE pd_year = '$year'");
while($row_search = mysqli_fetch_array($search)) {
EDIT
I have tried to build out the "WHERE" in the query dependent on the is_array check like this:
$where = "WHERE ";
if(!empty($pd_year_ex) && is_array($pd_year_ex)) {
$pd_y = $pd_year[0];
foreach ($pd_y as $year) {
$where .= "pd_year LIKE '%".$year."%'";
}
} elseif(!empty($pd_year_ex) && !is_array($pd_year_ex)) {
$where .= "pd_year LIKE '%".$pd_year_ex."%'";
} elseif(empty($pd_year_ex)) {
$where .= "";
}
and this doesn't seem to be working either. i am just trying to understand how to do a search like this:
$search = mysqli_query($con, "SELECT * FROM designs WHERE pd_year LIKE '%2017,2016,2015%'")(etc)
I know it won't go with the above, but how do i search a table for something like this?
sorry my English is weak ....
how can i search multi values from db SQL So that there was any.
i can search name && family together but
I want when the user searched name And family leave empty Return result correctly
how can i write this
if (isset($_POST['searchname']) || isset($_POST['searchfamily'])) {
$sql = "select * from myinfo WHERE name='{$_POST['searchname']}' && family='{$_POST['searchfamily']}' ORDER BY id DESC";
}
else {
$sql = "select * from myinfo ORDER BY id DESC";
}
Your 3 main issues here..
the first being WHERE name= now.. name is already used by mysql therefore you shouldn't use it however.. If you do use it run it like this:
WHERE `name`=
You should always backtick database tables and columns to make life easier in the long haul.
The second issue being you used && where it should be AND
the third is you shouldn't be placing your variables straight into your query as you're left open for SQL Injection.
Now I'm running on the assumption you're using $mysqli as your variable however, this may need adjusting to suit the correct variable you are using:
if (isset($_POST['searchname']) || isset($_POST['searchfamily'])) {
$searchName = $_POST['searchname'];
$family = $_POST['searchfamily'];
$sql = $mysqli->prepare("select * from `myinfo` WHERE `name` = ? OR `family`= ? ORDER BY `id` DESC");
$sql->execute([$searchName, $family]);
} else {
$sql = $mysqli->prepare("select * from `myinfo` ORDER BY `id` DESC");
$sql->execute();
}
If you want to search with both then you need to change your if also. And change && to and in your query
if (isset($_POST['searchname']) && isset($_POST['searchfamily'])) {
$sql = "select * from myinfo WHERE `name`='{$_POST['searchname']}' AND family='{$_POST['searchfamily']}' ORDER BY id DESC";
}
else {
$sql = "select * from myinfo ORDER BY id DESC";
}
Edit
As per your comment try this:
if (isset($_POST['searchname']) || isset($_POST['searchfamily'])) {
$where="";
if(isset($_POST['searchname']))
$where=" WHERE `name`='{$_POST['searchname']}'";
if(isset($_POST['searchfamily']))
{
if($where=="")
$where=" WHERE family='{$_POST['searchfamily']}'";
else
$where=" AND family='{$_POST['searchfamily']}'";
}
$sql = "select * from myinfo $where ORDER BY id DESC";
}
else {
$sql = "select * from myinfo ORDER BY id DESC";
}
Lets say the user only entered in an artist to search by, how do I get PHP to recognize that the user is only looking for an artist and should therefore setup a query only for the artist. The way I have currently done it works, but it is very ineffective when the user wants a variety of search options.
$artist = $_POST["artistSearch"];
$topic= $_POST["topicSearch"];
$date = $_POST["dateSearch"];
$title = $_POST["titleSearch"];
$artistLength = strlen($artist);
$topicLength = strlen($topic);
$dateLength = strlen($date);
$titleLength = strlen($title);
if ($artistLength>2 && $topicLength<2 && $dateLength<2 && $titleLength<2) {
$sql=("Select * FROM music WHERE artist = '$artist' ORDER BY date");
}
if ($artistLength>2 && $topicLength>2 && $dateLength<2 && $titleLength<2) {
$sql=("Select * FROM music WHERE artist = '$artist' AND topic = '$topic' ORDER BY date");
}
if ($artistLength>2 && $topicLength>2 && $dateLength>2 && $titleLength<2) {
$sql=("Select * FROM music WHERE artist = '$artist' AND topic = '$topic' AND date = '$date' ORDER BY date");
}
if ($artistLength>2 && $topicLength>2 && $dateLength>2 && $titleLength>2) {
$sql=("Select * FROM music WHERE artist = '$artist' AND topic = '$topic' AND date = '$date' AND title = '$title' ORDER BY date");
}
$result = mysqli_query($con,$sql);
Simple, you build up the query string in stages. Ignoring your sql injection attack vulnerability, and assuming that all options should be ANDed together, you can do something like:
$options = array();
if ($artist) {
$options[] = "artist = '$artist'";
}
if ($topic) {
$options[] = "topic = '$topic'";
}
etc...
$where_clause = implode(' AND ', $options);
$sql = "SELECT ... WHERE $where_clause";
I have the following code and all of the search functions work except for the title field. So I can search by genre, date, location etc... but not by title. When attempting to search by title nothing is returned at all. Can anyone help me with this?
Also, is there a more efficient way to count all the fields before limiting it for use in pagination later on?
$today = date("Y-m-d");
$query = "SELECT * FROM TABLE_NAME WHERE Date >= '$today'";
$bind = Array();
if ($_GET["Title"] && $_GET["Title"] != "") {
$query .= " and Title like %?%";
$bind['Title'] = $_GET['Title'];
}
if ($_GET["Genre"] && $_GET["Genre"] != "") {
$query .= " and Genre like %?%";
$bind['Genre'] = $_GET['Genre'];
}
if ($_GET["Location"] && $_GET["Location"] != "") {
$query .= " and Location like %?%";
$bind['Location'] = $_GET['Location'];
}
if ($_GET["Date"] && $_GET["Date"] != "") {
$query .= " and Date = %?%";
$bind['Date'] = $_GET['Date'];
}
$stmt = $db->prepare($query);
$stmt->execute($bind);
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
$num = count($rows);
$query .= " ORDER BY Date LIMIT $limit, 9";
$stmt = $db->prepare($query);
$stmt->execute($bind);
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
Edit: After everyone's help I thought I would post my now revised code for future reference. It turns out the other fields were not working, but instead due to the if statement all this was nested in the code simply wasn't being executed.
$today = date("Y-m-d");
$query = "SELECT * FROM TABLE_NAME WHERE Date >= '$today'";
$countq = "SELECT count(*) FROM TABLE_NAME WHERE Date >= '$today'";
$bind = Array();
if ($_GET["Title"] && $_GET["Title"] != "") {
$query .= " and Title like :title";
$countq .= " and Title like :title";
$bind[':title'] = "%{$_GET['Title']}%";
}
if ($_GET["Genre"] && $_GET["Genre"] != "") {
$query .= " and Genre like :genre";
$countq .= " and Genre like :genre";
$bind[':genre'] = "%{$_GET['Genre']}%";
}
if ($_GET["Location"] && $_GET["Location"] != "") {
$query .= " and Location like :loc";
$countq .= " and Location like :loc";
$bind[':loc'] = "%{$_GET['Location']}%";
}
if ($_GET["Date"] && $_GET["Date"] != "") {
$query .= " and Date = :date";
$countq .= " and Date = :date";
$bind[':date'] = "{$_GET['Date']}";
}
$stmt = $db->prepare($countq);
$stmt->execute($bind);
$rows = $stmt->fetchAll();
$num = count($rows);
$query .= " ORDER BY Date LIMIT $limit, 9";
$stmt = $db->prepare($query);
$stmt->execute($bind);
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
all of the search functions work
With the given query it is not true
From PDO tag wiki:
placeholders cannot represent an arbitrary part of the query, but a complete data literal only. Neither part of literal, nor whatever complex expression or a syntax keyword can be substituted with prepared statement.
Prepare FULL literal first: $name = "%$name%"; and then bind it.
As for the "more" efficient method for pagination - yes, oh yes.
With your current way of counting data you don't actually need other queries. as you have ALL the data already and can paginate it as well.
But of course it will pollute all the memory soon. So, if you want to get a count of rows from database, get the very count: run the same query but instead of SELECT * make it "SELECT count(*)
There are not any errors returned, that's why I am so confused
From PDO tag wiki again:
It is essential to set ERRMODE_EXCEPTION as a connection option as it will let PDO throw exceptions on connection errors. And this mode is the only reliable way to handle PDO errors.
I'm using the following code to sort MySQL queries into time/date:
mysql_select_db("user_live_now", $con);
$result = mysql_query("SELECT * FROM users_newest_post ORDER BY users_date_post DESC");
while($row = mysql_fetch_array($result))
{
print($row['user']);
}
instead of having the PHP run through and show all the values in the table can I have it show the values from an array?
So, you want to find specific users in the SQL query to return? Build your query programmatically:
$users = array('User1','John','Pete Allport','etc');
$sql = "SELECT * FROM `users_newest_post` WHERE ";
$i = 1;
foreach($users as $user)
{
$sql .= "`username` = '$user'";
if($i != count($users))
{
$sql .= " OR ";
}
$i++;
}
$sql .= " ORDER BY `users_date_post` DESC";
$result = mysql_query($sql);
Which would get you a query like:
SELECT * FROM `users_newest_post`
WHERE `username` = 'User1'
OR `username` = 'John'
OR `username` = 'Pete Allport'
OR `username` = 'etc'
ORDER BY `users_date_post`
DESC
So, you want to find all posts for a certain date or between two dates, kinda hard to do it without knowing the table structure, but you'd do it with something like this:
//Here's how to find all posts for a single date for all users
$date = date('Y-m-d',$timestamp);
//You'd pull the timestamp/date in from a form on another page or where ever
//Like a calendar with links on the days which have posts and pass the day
//selected through $_GET like page.php?date=1302115769
//timestamps are in UNIX timestamp format, such as you'd get from time() or strtotime()
//Note that, without a timestamp parameter passed to date() it uses the current time() instead
$sql = "SELECT * FROM `posts` WHERE `users_date_post` = '$date'"
$results = mysql_query($sql);
while($row = mysql_fetch_assoc($results))
{
echo $row['post_name'] . $row['users_date_post']; //output something from the posts
}
//Here's how to find all posts for a range of dates
$startdate = date('Y-m-d',$starttimestamp);
$enddate = date('Y-m-d',$endtimestamp);
//Yet again, date ranges need to be pulled in from somewhere, like $_GET or a POSTed form.
//Can also just pull in a formatted date rather than a timestamp and use it straight up instead, rather than going through date()
$sql = "SELECT * FROM `posts` WHERE `users_date_post` BETWEEN '$startdate' AND '$enddate'";
//could also do:
//"SELECT * FROM `posts` WHERE `users_date_post` > '$startdate' AND `users_date_post` < '$endate'"
$results = mysql_query($sql);
while($row = mysql_fetch_assoc($results))
{
//output data
}
To find posts for a specific user you would modify the statement to be something like:
$userid = 5; //Pulled in from form or $_GET or whatever
"SELECT * FROM `posts` WHERE `users_date_post` > '$startdate' AND `users_date_post` < '$enddate' AND `userid` = $userid"
To dump the result into an array do the following:
mysql_select_db("user_live_now", $con);
$result = mysql_query("SELECT * FROM users_newest_post ORDER BY users_date_post DESC");
while($row=mysql_fetch_assoc($result))
{
$newarray[]=$row
}
What you probably want to do is this:
$users = array("Pete", "Jon", "Steffi");
$users = array_map("mysql_real_escape_string", $users);
$users = implode(",", $users);
..("SELECT * FROM users_newest_post WHERE FIND_IN_SET(user, '$users')");
The FIND_IN_SET function is a but inefficient for this purpose. But you could transition to an IN clause with a bit more typing if there's a real need.
$sql = 'SELECT * FROM `users_newest_post` WHERE username IN (' . implode(',', $users) . ')';