How to SEARCH additional QUERY in datatable server-side - php

I'm using datatables server-side and everything worked as it should. Now i'm trying to SEARCH for the data gotten from the function attrib() in my code. This adds more information for each row but problem is - its data cannot be searched.
This is understandable because it does not exist within the main $sql query used for searching the database. Is there a way around this?
I know this maybe difficult to understand so i'm trying to be as clear as possible. Please, ask for more clarification if you can help. Thanks.
$sql = "SELECT mat_code,mat_descp,short_code_details,approverComment,date_created,
mt.mat_type, mt.mat_desc,
vc.val_class,vc.val_class_desc,
vc.val_cat_code,vc.val_cat_desc,
n.noun_name,n.qualifier,n.shorttext_item,
u.uombs,
mg.mtgp_id,mg.mtgp_desc,
pt.plant_name,
sl.sl_id,sl.sto_loc_name,
pg.pur_id,pg.purchs_gp_name,
us.fname,us.lname,mat_status
FROM mat_master_head mmh
INNER JOIN material_type mt ON mmh.mat_type = mt.mat_type
LEFT OUTER JOIN valuation_class vc ON mmh.val_class_id = vc.id
INNER JOIN noun n ON mmh.noun_id = n.noun_id
INNER JOIN uom_bs u ON mmh.uombs_id = u.uombs_id
INNER JOIN material_group mg ON mmh.mg_id = mg.id
INNER JOIN plant pt ON mmh.plant_id = pt.plant_id
INNER JOIN storage_location sl ON mmh.sl_id = sl.id
INNER JOIN purchase_gp pg ON mmh.pur_id = pg.pur_id
INNER JOIN users us ON mmh.user_id = us.id
WHERE (1=1)";
// AND mat_status = 4 AND (download_status = 0 OR download_status = 1)
if( !empty($requestData['search']['value']) ) { // if there is a search parameter, $requestData['search']['value'] contains search parameter
$sql.=" AND ( mat_code LIKE '%".$requestData['search']['value']."%' ";
$sql.=" OR plant_name LIKE '%".$requestData['search']['value']."%' ";
$sql.=" OR sto_loc_name LIKE '%".$requestData['search']['value']."%' ";
$sql.=" OR noun_name LIKE '%".$requestData['search']['value']."%' ";
$sql.=" OR qualifier LIKE '%".$requestData['search']['value']."%' ";
$sql.=" OR shorttext_item LIKE '%".$requestData['search']['value']."%' ";
$sql.=" OR short_code_details LIKE '%".$requestData['search']['value']."%' ";
$sql.=" OR uombs LIKE '%".$requestData['search']['value']."%' ";
$sql.=" OR mat_descp LIKE '%".$requestData['search']['value']."%' ";
$sql.=" OR fname LIKE '%".$requestData['search']['value']."%' ";
$sql.=" OR lname LIKE '%".$requestData['search']['value']."%' ";
$sql.=" OR date_created LIKE '%".$requestData['search']['value']."%' )";
}
$query = $conn->query($sql);
$totalFiltered = $query->rowCount(); // when there is a search parameter then we have to modify total number filtered rows as per search result.
if( !empty($requestData['order'][0]['column']) || !empty($requestData['order'][0]['dir']) || !empty($requestData['start']) || !empty($requestData['length'])) {
$sql.=" ORDER BY ". $columns[$requestData['order'][0]['column']]."
".$requestData['order'][0]['dir']." ";
$sql.=" LIMIT ".$requestData['start']." , ".$requestData['length']." ";
/* $requestData['order'][0]['column'] contains colmun index, $requestData['order'][0]['dir'] contains order such as asc/desc */
}
$query = $conn->query($sql);
///Attribute Function//////////////////////////////////
function attrib($mat_code)
{
global $conn;
$mat_query = "SELECT a.attributes, mmd.attr_value, u.uombs FROM mat_master_details mmd
INNER JOIN attribute a ON mmd.attr_id = a.attr_id
INNER JOIN uom u ON a.uombs_id = u.uombs_id
WHERE mat_code = '$mat_code' AND mmd.attr_value >= '0'";
$mat = $conn->query($mat_query);
$attribs = '';
foreach($mat as $mats){
$attribs .= removeSlash($mats['attributes'].' - '.$mats['attr_value'].''.$mats['uombs'].' ');
}
return '<span class="colortxt3">'.$attribs.'</span>';
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////
$data = array();
foreach ($query as $row) { // preparing an array
$nestedData=array(); //new array to display list
$nestedData[0] = $row['mat_code'];
$nestedData[1] = MatStatus($row['mat_status']);
$nestedData[2] = '<span class="lgtxt">'.'PLANT:'.' '.'</span>'.'<span class="colortxt">'.$row['plant_name'].'</span>'.' '.
'<span class="lgtxt">'.'STORAGE LOCATION:'.' '.'</span>'.'<span class="colortxt">'.$row['sto_loc_name'].'</span>'.' '.'<br>'.
'<span class="lgtxt">'.'NOUN:'.' '.'</span>'.'<span class="colortxt">'.$row['noun_name'].'</span>'.' '.
'<span class="lgtxt">'.'QUALIFIER:'.' '.'</span>'.'<span class="colortxt">'.$row['qualifier'].'</span>'.' '.
'<span class="lgtxt">'.'SHORT TEXT:'.' '.'</span>'.'<span class="colortxt">'.$row['shorttext_item'].''.removeSlash($row['short_code_details']).'</span>'.' '.
'<span class="lgtxt">'.'BASE UOM:'.' '.'</span>'.'<span class="colortxt">'.$row['uombs'].'</span>'.' '.'<br>'.
'<span class="lgtxt">'.''.'</span>'.'<span class="colortxt4">'.$row['mat_descp'].'</span>'.' '.
'<span class="colortxt3">'.attrib($nestedData[0]).'</span>'.' '.'<br>'.
'<span class="lgtxt">'.'CREATED BY:'.' '.'</span>'.'<span class="colortxt2">'.$row['fname']." ". $row['lname'].'</span>'.' '.
'<span class="lgtxt">'.'DATE CREATED:'.' '.'</span>'.'<span class="colortxt2">'.$row['date_created'].'</span>';
$nestedData[3] = 'View';
$data[] = $nestedData;
}

You're not making this easy. First of all 'datatables' could refer to several things. Just 'tables' with 'data', but I guess it is https://datatables.net
There's a function attrib() in your code, but what does it do?! Its name doesn't tell me anything and the comment above it says: "Attribute Function", which is not very enlightening. Ok, it executes a query, I see.
So you output a column in your 'datatable' of which the values come from a query and you want to be able to search that value before you select the row for displaying.
A simple solution would be to put the result of attrib() in a column of a table you are searching through. This might be against database normalization rules, but then again it will be the fastest and easiest solution. Just keep in might that you need to update the value in that column every time any of the values, which attrib() depends upon, changes. So, that makes this solution rather ugly.
The other solution would be to incorporate the query in attrib() as a subquery in your main search query. Given that your search query is already quite complex, this might, in the end, create a very sluggish query. It is however the best solution. In its most basic form it would look something like this:
$sql .=" OR (SELECT ... FROM ... WHERE ....) LIKE '%".$requestData['search']['value']."%' ";
To read more about subqueries see: https://dev.mysql.com/doc/refman/8.0/en/subqueries.html
I would urge you to write more readable code. Do not use so many abbreviations, what does uombs or mtgp mean? You are using a higher level language because that makes your code easier to understand, so don't undermine it. Also write comments that are useful, don't use them as seperators in your code.

Related

Search with multiple tables & ORDER BY php mysql

I have a script i want to search multiple tables how can i do that.
**Also add ORDER BY function in Mysql query **
help is appreciated.
if(isset($_GET["search"]))
{
$condition = '';
//$query = explode(" ", $_GET["search"]);
$query = explode(" ", $_GET["search"]);
foreach($query as $text)
{
$condition .= "title LIKE +'%".mysqli_real_escape_string($connect, $text)."%' OR ";
}
$condition = substr($condition, 0, -4);
$sql_query = "SELECT * FROM countries WHERE " . $condition;
$result = mysqli_query($connect, $sql_query);
if(mysqli_num_rows($result) > 0)
{
while($row = mysqli_fetch_array($result))
{
echo '<tr><td>'.$row["title"].'</td></tr>';
}
}
else
{
echo '<label>Data not Found</label>';
}
}
SELECT * FROM (
(SELECT title FROM countries WHERE title LIKE '%mystring%')
UNION
(SELECT title FROM locations WHERE title LIKE '%mystring%')
) ta
That's the sql, but would need to point out the drawbacks of using union as a search tool.
a) The longer the tables get the longer the search will get, you can add in Limits on each query and then on the union as a whole - but it's not a winner.
b) The table columns have to match up so you'll need perhaps to do myID as ID, then you will need an extra column to say which each is (0=country, 1= location)
c) I guess you are trying to do a site search of sorts, in which case there isn't a relevance in this instance.
Hence I would use something like http://sphinxsearch.com/ bit tricky to get started, but a really quick search engine. If you have a large site. Otherwise look into mysql full text searches which also have relevence and are built in so easier to get started with.

keyword mysql search returning inaccurate results

I am using the code below to search my database based on keywords given by the user. It seems to work fine for the most part, but i am searching both based on location and keywords. This is where I have the issues.
If i put no location in and search it returns all results regardless of location, which is fine. If i put in a location that does not exist and some keywords, It returns all results matching the keywords and seems to ignore the location.
Also if i leave the keywords empty and search by a location that does exist, it seem that it ignores the location again and just returns all results.
So it would seem my logic for setting the location is not working.
$keys = explode(" ",$tag);
$search_sql = "SELECT DISTINCT providers.* FROM providers JOIN provider_tags ON providers.id = provider_tags.provider_Id JOIN tags ON provider_tags.tag_id = tags.id WHERE tags.tag_name LIKE '%$tag%' OR providers.provider_name LIKE '%$tag%' OR providers.provider_contact_name LIKE '%$tag%' OR providers.provider_features LIKE '%$tag%' ";
foreach($keys as $k){
$search_sql .= " OR tags.tag_name LIKE '%$k%' OR providers.provider_name LIKE '%$k%' OR providers.provider_contact_name LIKE '%$k%' OR providers.provider_features LIKE '%$k%' ";
}
$search_sql .= " AND (providers.provider_town LIKE '%{$location}%' OR providers.provider_local_area LIKE '%{$location}%' OR providers.provider_postcode LIKE '%{$location}%')";
echo $search_sql;
$gettags = mysqli_query($con, $search_sql) or die(mysqli_error($con));
You are adding a bunch of OR conditions in a loop and then a big AND condition for the location. Your AND condition is checked with the last OR of the loop. If any of the others OR in the condition is true then you get a result no matters the AND condition.
Edit :
You'll probably get the results you want if you :
wrap every OR conditions with parenthesis;
wrap all the OR conditions together.
Something like :
$search_sql = "SELECT DISTINCT providers.* FROM providers JOIN provider_tags ON providers.id = provider_tags.provider_Id JOIN tags ON provider_tags.tag_id = tags.id WHERE ( (tags.tag_name LIKE '%$tag%' OR providers.provider_name LIKE '%$tag%' OR providers.provider_contact_name LIKE '%$tag%' OR providers.provider_features LIKE '%$tag%') ";
foreach($keys as $k){
$search_sql .= " OR (tags.tag_name LIKE '%$k%' OR providers.provider_name LIKE '%$k%' OR providers.provider_contact_name LIKE '%$k%' OR providers.provider_features LIKE '%$k%') ";
}
$search_sql .= ") AND (providers.provider_town LIKE '%{$location}%' OR providers.provider_local_area LIKE '%{$location}%' OR providers.provider_postcode LIKE '%{$location}%')";

Using WHERE in a multiple query

This is based on a search engine
I am receiving duplicate search results from this...
$construct ="SELECT * FROM Rating, Attraction WHERE $construct" ;
Then I was informed that it was selecting all results and rows and therefore repeating it so i used this query from another page I have and added the relevant WHERE on the bottom.
$construct = "SELECT Attraction.*, Type.TypeName, Rating.RatingUrl ";
$construct .= "FROM Attraction ";
$construct .= "INNER JOIN Type ON Attraction.Type = Type.TypeID ";
$construct .= "INNER JOIN Rating ON Attraction.AttractionID = Rating.AttractionID ";
$construct .= "WHERE Attraction = '$construct' ";
Have do i structure this correctly, it is not working and recognising the query.
$construct is a query for matching keywords with the database
The var you store your query in is called $construct and you are also including it on the last line "WHERE Attraction = '$construct' " so you are actually including the first 4 lines inside the last line, which wont give desired result.
Perhaps renaming the query variable to make it work is enough.
Also if you dont want duplicates, just use DISTINCT
SELECT DISTINCT * FROM Rating, Attraction WHERE $construct
I believe it is because of this
$construct .= "WHERE Attraction = '$construct' ";
U are using the same variable name ?
i am not sure but please user group by TypeID may be its work

Query error MySQL php

Im new to php and my sql in trying to get all the results from this table if nothing is selected but for some reason its always displaying one result. Any ide why
$query = "SELECT *, ROUND(AVG(d.rating),0) FROM restaurant AS r, review AS d WHERE 1=1 ";
if($vicinity) $query .= "AND r.vicinity=\"$vicinity\" ";
if($cuisine) $query .= "AND r.cuisine=\"$cuisine\" ";
if($price) $query .= "AND r.price=\"$price\"";
if($name) $query .= "AND r.name LIKE \"%$name%\"";
$result = mysql_query($query);
while($row = mysql_fetch_array($result)) {
and im only getting the first item on the table
I would look into PDO personally. You can find out a lot about it in the manual here.
guessing you're only getting one result because the avg call without a group by is triggering some interesting behavior. try adding a group by, and i'm guessing you also want to associate the restaurants and reviews with a join. eg:
$query = "SELECT *, ROUND(AVG(d.rating),0) FROM restaurant AS r LEFT JOIN review AS d on r.id = d.restaurant_id WHERE 1=1";
...
...
$query .= ' GROUP BY r.id';
$result = mysql_query($query);
per the thread, sounds like you should look into prepared statements as well :). and the SELECT * should probably also just be SELECT r.* - the data returned as part of the * results from the rating won't be meaningful after the group by (the r.* and round(avg(d.rating),0) values should be though)
Try to use prepared statements and get results and use iterator to parse and print in a loop will get. See also this tutorial.

php select statement dependent on variables existing

I am trying to set up a filter system for a small shop I am developing. Basically, I am working the results off a list of variables. the page, products.php if there is no querystring will show all products. However, if there is a variable present I want it to alter the select statement where necessary.
however, I am having problems filtering. If i use the AND statement for all variables it does not filter appropriately neither does the OR. So if i wanted black size 5 shoes it would show all size fives regardless of color.
Is there a better approach to take with this as is becoming a fair old head scratcher!
if ($queryString == NULL){
$query = "SELECT * FROM store_products
JOIN store_cat on store_products.cat=store_cat.cat_id
JOIN prod_sizes on store_products.prod_id=prod_sizes.product_id
JOIN prod_color on store_products.prod_id=prod_color.product_id
GROUP BY store_products.prod_id";
}else{
$query = "SELECT * FROM store_products
JOIN store_cat on store_products.cat=store_cat.cat_id
JOIN prod_sizes on store_products.prod_id=prod_sizes.product_id
JOIN prod_color on store_products.prod_id=prod_color.product_id
where store_products.sale='$sale' OR prod_color.color='$color' OR prod_sizes.size='$size' OR store_products.cat='$cat' GROUP BY store_products.prod_id";
}
example variable string
products.php?sale=&cat_id=1&size=&color=Yellow
Try building your WHERE criteria before running the query.
String:
products.php?sale=&cat_id=1&size=&color=Yellow
myfile.php
$criteria = "WHERE 1 ";
if (isset($_GET['sale']) {
$criteria .= "AND tore_products.sale=$_GET['sale'] ";
}
if (isset($_GET['cat_id']) {
$criteria .= "AND store_products.cat=$_GET['cat_id'] ";
}
if (isset($_GET['color']) {
$criteria .= "AND tore_products.color=$_GET['color'] ";
}
And so on then run your query:
$query = "SELECT * FROM store_products
JOIN store_cat on store_products.cat=store_cat.cat_id
JOIN prod_sizes on store_products.prod_id=prod_sizes.product_id
JOIN prod_color on store_products.prod_id=prod_color.product_id
$criteria
GROUP BY store_products.prod_id";
And please remember to clean your $_GET variables prior to querying with them using mysql_real_escape_string, mysqli or PDO!
$query = "SELECT * FROM store_products
JOIN store_cat on store_products.cat=store_cat.cat_id
JOIN prod_sizes on store_products.prod_id=prod_sizes.product_id
JOIN prod_color on store_products.prod_id=prod_color.product_id ";
if {$queryString != NULL){
$query .= " WHERE tore_products.sale='$sale' OR prod_color.color='$color' OR prod_sizes.size='$size' OR store_products.cat='$cat'"
}
$query .=" GROUP BY store_products.prod_id;"
Then you execute your Query :)

Categories