Refining PDO results from MySQL database with Text Box - php

I'm currently retrieving data from a MySQL database using PDO. I'm using a foreach to display the data onto a page, and wish for the user to be able to enter a search term into a input field, hit the submit button, and then only results who's title contains the search term are returned.
Here is my current code:
file_functions.php - Where the SQL query function is located
function getbycategory($category, $limit){
global $db;
if (isset($category) AND $category != "all") {
$sm = $db->prepare ("SELECT * FROM parts WHERE main_category = :category");
$sm->bindParam(':category', $category, PDO::PARAM_INT);
} else {
$sm = $db->prepare ("SELECT * FROM parts");
}
$sm->execute();
return $sm->fetchAll();
}
files.php - Where the results are displayed
$files = getbycategory($_GET['filter']);
foreach($files as $file){
echo'<div class="col-lg-" id="file-'.$file['id'].'">
<div class="file-list-item first" id="">
<img class="file-image" height="120px" width="180px" src="'.$file['image_url'].'" />
<div class="file-text">
<h3><strong>'.$file['name'].'</strong></h3>
Submitted by: '.$file['submitter'].'<br/>
Author: '.$file['author'].'<br />
Category: '.ucfirst($file['subcategory']).'<br />
Description: '.substr($file['description'],0,45).'...
</div>
<div class="download">
<a target="_blank" href="'.$file['download_url'].'" class="btn-success btn btn-default">Download</a>
Report as Broken<br /><br />';
if($file['is_broken']){
echo '<span class="broken"><i data-toggle="tooltip" data-placement="left" id="broken" title="This file has been reported as broken and is awaiting review." class="fa fa-warning fa-2x"></i></span>';
}
echo '
</div>
</div>
</div>';
};
?>
Below is the form used to refine the results. Currently the filter dropdown menu works for the filter, but the search term does not. This is what I wish to implement
<form method="get">
<select name="filter">
<option <?php if($_GET['filter'] == "all" OR !isset($_GET['filter'])){echo 'selected';} ?> value="all">View All Files</option>
<option <?php if($_GET['filter'] == "1") {echo 'selected';} ?> value="1">View Vehicles Only</option>
<option <?php if($_GET['filter'] == "2") {echo 'selected';} ?> value="2">View Lighting Equiptment</option>
</select>
<input type="submit" value="Filter Results"/><br /><br />
<input type="text" name="search" placeholder="Enter a search term" />
<input type="submit" value="Search Results"/>
</form>
To summarise, I wish to use the text field in the bottom snippet of code to refine the results displayed in files.php by comparing their title to the search term.
I wish to compare the search term to the $file['name'].
Many thanks.

Ok, let me step you through it using a simple LIKE comparison...
First, the method signature. Globals are a bad idea so we'll include the PDO instance
function getbycategory(PDO $db, $category = null, $search = null, $limit = null)
Now, build the query and collect parameters as you go.
$params = [];
$where = [];
if ($category !== null) {
$where[] = 'main_category = :category';
$params[':category'] = [
'val' => (int) $category,
'type' => PDO::PARAM_INT
];
}
if ($search !== null) {
$where[] = "LOWER(`name`) LIKE CONCAT('%', LOWER(:search), '%')";
$params[':search'] = [
'val' => (string) $search,
'type' => PDO::PARAM_STR
];
}
$query = sprintf('SELECT * FROM `parts` %s', implode(' AND ', $where));
if ($limit !== null) {
$query .= ' LIMIT :limit';
$params[':limit'] = [
'val' => (int) $limit,
'type' => PDO::PARAM_INT
];
}
$stmt = $db->prepare($query);
foreach ($params as $key => $param) {
// use bindValue to avoid problems with variable references in the loop
// see http://stackoverflow.com/questions/4174524/binding-params-for-pdo-statement-inside-a-loop
$stmt->bindValue($key, $param['val'], $param['type']);
}
$stmt->execute();
return $stmt->fetchAll(PDO::FETCH_ASSOC);

Related

Filtering search results PHP

I'm trying to give a user the ability to filter search results by ascending or descending order. It isn't working.
I think it is an issue with my select or post method or something.
What could be the reason why it isn't working?
<?php
$search = "";
if(isset($_POST["search"])){
$search = $_POST["search"];
$Ascending= $_POST["Sort By"];
$Descending= $_POST["Sort By"];
}
?>
<form method="POST">
<input type="text" name="search" placeholder="Search for Question"
value="<?php echo $search;?>"/>
<label for="Sort">SortBy:</label>
<select id="SortBy" name="Sort By">
<option value="Ascending">Ascending Order</option>
<option value="Descending">Descending Order</option>
<input type="submit"
</select>
</form>
<?php
if(isset($Ascending)) {
if (isset($search)) {
require("common.inc.php");
$query = file_get_contents(__DIR__ . "/queries/SearchTableASC.sql");
if (isset($query) && !empty($query)) {
try {
$stmt = getDB()->prepare($query);
//Note: With a LIKE query, we must pass the % during the mapping
$stmt->execute([":question" => $search]);
//Note the fetchAll(), we need to use it over fetch() if we expect >1 record
$results = $stmt->fetchAll(PDO::FETCH_ASSOC);
} catch (Exception $e) {
echo $e->getMessage();
}
}
}
}
if(isset($Descending)){
if (isset($search)) {
require("common.inc.php");
$query = file_get_contents(__DIR__ . "/queries/DescendingOrder.sql.sql");
if (isset($query) && !empty($query)) {
try {
$stmt = getDB()->prepare($query);
//Note: With a LIKE query, we must pass the % during the mapping
$stmt->execute([":question" => $search]);
//Note the fetchAll(), we need to use it over fetch() if we expect >1 record
$results = $stmt->fetchAll(PDO::FETCH_ASSOC);
} catch (Exception $e) {
echo $e->getMessage();
}
}
}
}
?>
<!--This part will introduce us to PHP templating,
note the structure and the ":" -->
<!-- note how we must close each check we're doing as well-->
<?php if(isset($results) && count($results) > 0):?>
<p>This shows when we have results</p>
<ul>
<!-- Here we'll loop over all our results and reuse a specific template for each iteration,
we're also using our helper function to safely return a value based on our key/column name.-->
<?php foreach($results as $row):?>
<li>
<?php echo get($row, "question")?>
Delete
</li>
<?php endforeach;?>
</ul>
<?php else:?>
<p>This shows when we don't have results</p>
<?php endif;?>
You are not using the incoming parameters correctly:
$Ascending= $_POST["Sort By"];
$Descending= $_POST["Sort By"];
Here you set ascending and descending to the same value.
You should do something like:
$ascOrDec = $_POST['Sort By'];
And than check the value of $ascOrDec before you choose your query.

My Select form is not displaying database items

I am attempting to create a form where the user can insert a product into a database. One of the the things they must input is the category, which I am using a select input form to allow them to choose from the available categories (PHP and MySQL displays all the available categories). The options inside the select element is given with PHP. But for some reason, when I run the application, the categories do not show up. No errors or anything, and the connection to the database is assured. The code is below. I am using the MVC pattern, if that helps any
The file with the function (category_db.php)
<?php
function get_categories() {
global $db;
$query = "SELECT * FROM categories ORDER BY categoryID";
$statement= $db->prepare($query);
$statement->execute();
return $statement;
}
The controller for the files (index.php)
<?php
require ('../models/database.php');
require ('../models/product_db.php');
require ('../models/category_db.php');
$action = filter_input(INPUT_POST, 'action');
if($action == NULL || $action==FALSE){
$action = 'list_products';
}
if ($action == 'list_products'){
$categories = get_categories();
$category_id = filter_input(INPUT_GET, 'category_id');
if ($category_id == NULL || $category_id == FALSE){
$category_id = 1;
}
$product_item = get_product_list($category_id);
include ('product_list.php');
} else if ($action = 'delete_product') {
$product_id = filter_input(INPUT_POST, 'product_id');
$category_id = filter_input(INPUT_POST, 'category_id');
delete_product($product_id);
header("Location: .?category_id=$category_id");
}
else if($action == 'add_product'){
$categories = get_categories();
include('add_product_form.php');
}
And finally, the page that display the form (add_product_form.php)
<?php include '../includes/header.php'; ?>
<main>
<h3>Add Product Form</h3>
<form method="post" action=".">
<label for="category">Category</label>
<select name="category">
<?php foreach ( $categories as $category ) : ?>
<option value="<?php echo $category['categoryID']; ?>">
<?php echo $category['categoryName']; ?>
</option>
<?php endforeach; ?>
</select>
<br>
<label for="product_code">Product Code</label>
<input type="text" name="product_code"><br>
<label for="product_name">Product Name</label>
<input type="text" name="product_name"><br>
<label for="list_price">List Price</label>
<input type="text" name="list_price"><br>
<input type="submit" value="Add Product">
</form>
</main>
<?php include '../includes/footer.php'; ?>
Now I have triple checked the code, but I cannot find the problem. Any help on this would be appreciated. I am also using netbeans if that helps any
I think you should use a "fetchAll" in your function so you will return an array with all your categories :
function get_categories() {
global $db;
$query = "SELECT * FROM categories ORDER BY categoryID";
$statement= $db->prepare($query);
$statement->execute();
$categories = $statement->fetchAll(PDO::FETCH_ASSOC);
return $categories;
}
Then you can loop throught the array to get the data you want.

Creating a search function

I have multiple fields in my search form and my query works for individual fields. what i'm trying to achieve is
1- query should work if search is based on 1 field
2- query should work if search is based on multiple fields entry
my form
<form class="sidebar-search jumbro-search container list-inline center-block" method="get" action="search.php">
<div class="form-group col-md-2">
<input list="location" name="location" class="form-control" placeholder="Location">
<datalist id="location">
<?php
$loc="select * from locations";
$results=mysqli_query($dbc,$loc);
while($row_loc=mysqli_fetch_array($results)){
echo '<option value='.$row_loc['region'].'>'.$row_loc['region'].'</option>';
}
?>
</datalist>
</div>
<div class="form-group col-md-2">
<select class="form-control" name="category">
<option selected>Category</option>
<?php
$cat="select * from property_type order by type_name asc";
$results=mysqli_query($dbc,$cat);
while($row_cat=mysqli_fetch_array($results)){
echo '<option value='.$row_cat['type_name'].'>'.$row_cat['type_name'].'</option>';
}
?>
</select>
</div>
<div class="form-group col-md-2">
<select class="form-control" name="status">
<option selected>Status</option>
<?php
$status="select * from property_status order by status_name asc";
$results=mysqli_query($dbc,$status);
while($row_status=mysqli_fetch_array($results)){
echo '<option value='.$row_status['status_name'].'>'.$row_status['status_name'].'</option>';
}
?>
</select>
</div>
<div class="form-group col-md-2">
<input type="text" name="price-max" value="999999999999" class="form-control" placeholder="Max Price">
</div>
<div class="form-group col-md-2">
<button class="btn btn-primary form-control">Search</button>
</div>
and my php script looks like this
// getting user data from search form
$location=$_GET['location'];
$category=$_GET['category'];
$status=$_GET['status'];
//scripts
if($location!="location" && $category!="category" && $status!="status"){
$query="select * from properties where `property_type` like '%$category%' && `location` like '%$location%' && `status` like '%$status%' ";
}
$query="select * from properties where `property_type` like '%$category%' or `location` like '%$location%' or `status` like '%$status%'";
$result=mysqli_query($dbc,$query);
if(mysqli_query($dbc,$query)) {
$num_rows=mysqli_num_rows($result);
} else {
echo 'Query failed';
}
$num_rows=mysqli_num_rows($result);
if($num_rows!=0){
echo '<h3 class="page-header text-center">'.$num_rows.' Match Found</h3>';
while ($row=mysqli_fetch_array($result)) {
<?php
}//end while
}else{
echo '<h3 class="page-header text-center">No Match Found, try adjusting your search criteria.</h3>';
include 'functions/latest-sc.php';
}
Well, okay, I have several ideas about what you should change in your code.
I strongly recommend you to separate representative logic (html and echoing variables) from functionality like defining variables and handling database queries. It will help you a lot in future.
You can use default option in your selects with empty value
<option value="">Select none</option>
It will simplify your code in checks:
Instead of:
if($location!="location" && $category!="category" && $status!="status")
Can use:
if($location && $category && $status)
Read about escaping
On your main question - you can create query by concatenation. I give you example and you can replace it with 'OR' or 'AND' for your needs:
$sql = 'SELECT * FROM properties WHERE ';
$scopes = [];
foreach([$location,$category,$status] as $column => $condition) {
if ($condition) {
$scopes[] = $column.' LIKE \'%.$condition.'%\'';
}
}
$scopes = implode(' AND ',$scopes);
$sql .= $scopes.';';
// ...do what you need
There is a lot more advices for coding but maybe you just present it like dead-simple example, so I skip it.
OK I think what you are asking is a SELECT based on multiple columns in a table. Below is a script from my application that selects records from a table that checks for a hometeam and an away team:-
<?php
$servername = "localhost";
$username = "root";
$password = "";
$dbname = "localdb";
// Create connection
$conn = new mysqli($servername, $username, $password, $dbname);
// Check connection
if ($conn->connect_error) {
die("Connection failed: " . $conn->connect_error);
}
$sql = "SELECT hometeam FROM stats WHERE hometeam = 'Man City' AND awayteam = 'Sunderland'";
$result = $conn->query($sql);
if ($result->num_rows > 0) {
// output data of each row
while($row = $result->fetch_assoc()) {
echo $row['hometeam'];
}
} else {
echo "0 results";
}
$conn->close();
?>
This should work:
$data = [
'property_type' => 'category_value', //$_GET['location']
'category' => 'location_value', //$_GET['category']
'status' => 'status_value' //$_GET['status']
];
$select = "";
$params = 0;
foreach($data as $k => $v){
if($params > 0){
$select .= " or ";
}
//add some better conditions
if(strlen($v) > 0){
$select .= "`$k` LIKE %$v%";
$params++;
}
}
$query = "select * from properties where " . $select;
print_r($query);

Dealing with search query and action

I did a search feature that will enable users to search and see result from database.
First - I want to transfer the search query (What the user searched for) into the search action (searchact.php)
When A user fills the input field below (form) and hit search...
<form action="searchact.php" class=" form-inline" method="post">
<div class="form-group">
<input type="text" name="word" class="form-control" placeholder="House key word">
</div>
<div class="form-group">
<select name="location" class="form-control">
<option value="Bosso">Bosso Campus</option>
<option value="GK">Gidan Kwano Campus (GK)</option>
</select>
</div>
<div class="form-group">
<select name="price" class="form-control">
<option>10-49k</option>
<option>50-99k</option>
<option selected>100-149k</option>
<option>150-199k</option>
</select>
</div>
<input type="submit" class="submit" name="submit" value="Search...">
</form>
I want the next page url (searchact.php) to be something like
wwww.test.com/searchact.php?q=word&location=Bosso&price=10-49k
This is searchact.php
<?php
if($_POST["submit"])
{
$word = $_POST["word"];
$location = $_POST["location"];
$price = $_POST["price"];
$sql = "INSERT INTO search (word,location,price) VALUES (:word,:location,:price)";
$q = $connecDB->prepare($sql);
$q->execute(array(':word'=>$word, ':location'=>$location, ':price'=>$price));
if($q)
{
$query = "SELECT * FROM house WHERE location LIKE :location AND tag LIKE :info AND range LIKE :range order by id desc LIMIT 10";
$stmt = $connecDB->prepare($query);
$stmt->bindValue(':info', '%' . $word . '%', PDO::PARAM_INT);
$stmt->bindValue(':location', '%' . $location . '%', PDO::PARAM_INT);
$stmt->bindValue(':range', '%' . $price . '%', PDO::PARAM_INT);
$stmt->execute();
if ($stmt->rowCount() > 0) {
$result = $stmt->fetchAll();
foreach( $result as $row ) {
$hid=$row["id"];
$name=$row["name"];
?>
<!--Some Html-->
<?php
}}
else {
echo 'No result found';
}
}}
?>
2nd - How do I make sure that a user actually searched for something without manually visiting "searchact.php"
Like.. How do I redirect a user to an error page when they just visit the searchact.php without inputing any search query.

PHP search script for multiple words

I have the following issue:
I can't search multiple words.
I have a search engine who search just the full string:
PHP Code:
function ft_search_sidebar() {
$sidebar[] = array(
"id" => "search_1",
"content" => '<div class="section">
<h2>'.t('Search files & folders').'</h2>
<form action="" method="post" id="searchform">
<div>
<input type="text" name="q" id="q" size="16" value="'.$_REQUEST['q'].'" />
<input type="button" id="dosearch" value="'.t('Search').'" />
</div>
<div id="searchoptions">
<input type="checkbox" name="type" id="type" checked="checked" /> <label for="type">'.t('Search only this folder and below').'</label>
</div>
<div id="searchresults"></div>
</form>
</div>'
);
return $sidebar;
}
function ft_search_ajax($act) {
if ($act = '%search%') {
$new = array();
$ret = "";
$q = $_POST['q'];
$type = $_POST['type'];
if (!empty($q)) {
if ($type == "true") {
$list = _ft_search_find_files(ft_get_dir(), $q);
} else {
$list = _ft_search_find_files(ft_get_root(), $q);
}
Can someone help me?
Grtz
You will need to either develop a search engine which is capable of multi keyword search or simply extract out all the keywords from the search string and then use the search engine multiple times for each keyword. Like this:
$q = $_POST['q'];
$type = $_POST['type'];
if (!empty($q)) {
if(strpos(trim($q),' ') > 0)
{
$array = explode(' ',trim($q));
foreach($array as $key=>$value)
{
//process search multiple times for different values of $value
}
}
else
{
if ($type == "true")
{
$list = _ft_search_find_files(ft_get_dir(), $q);
}
else
{
$list = _ft_search_find_files(ft_get_root(), $q);
}
}

Categories