Imploding an array into a MySQL query - php

so I have a blog system, and i want to build a section for "related news", I am not making a 'Tags' system but just simply searching and storing the current title of the article (which is pulled from the database) in a string and exploding it to be able to later put all the words into a query, that later query will search all titles in the database to find any of those words, and if it does, it will return the title in a list. Here is the relevant code:
// note to stackoverflow peeps, $row_object_title is just the title that is pulled form the database
$row_object_title_lower = strtolower($row_object_title);
$keywords = explode(" ",$row_object_title_lower);
Code that is run later on the page:
$keywords_imploded = implode("','",$keywords);
$myquery = sql_query("SELECT object_title FROM table WHERE object_title IN ('$keywords_imploded')
Now i try to list the titles by printing the title out, but nothing is display.
I am sure there is matching titles in the database.
Thanks

Your array of keywords is generated with:
$keywords = explode(" ",$row_object_title_lower);
What if you have a title like "My Super Blog Post"? You're going to get:
$keywords = array( "My", "Super", "Blog", "Post" );
Later on, you query using those values imploded together:
$keywords_imploded = implode("','",$keywords);
$myquery = sql_query("SELECT object_title FROM table WHERE object_title IN ('$keywords_imploded')
The SELECT query is going to look like this:
SELECT object_title FROM table WHERE object_title IN ( 'My', 'Super', 'Blog', 'Post' );
I don't think that's going to find anything.
You need to re-evaluate how you're handling the list of titles (I think that's what you're going for, right?).

It seems as though you have misunderstood how the IN clause works.
The IN clause will look for what is on the left in the list of values on the right. For example: WHERE id IN (2,3,5) - if id is in that list it will return true. In your case it is the opposite.
Something like this should work for what your after but there are likely to be better alternatives.
$sql = '';
foreach ($keywords AS $keyword)
{
if ($sql != '')
$sql .= ' OR ';
$sql .= "object_title LIKE '%$keyword%'";
}
$query = 'SELECT object_title FROM table WHERE '.$sql;
% is a wildcard.
Just please remember to escape the values first.

Try:
$keywords_imploded = join("','", $keywords);
$myquery = sql_query("SELECT object_title FROM table WHERE object_title IN ($keywords_imploded)

Related

PHP MySqli show result for similar terms (Keyword)

Let me explain fast what i want to do!
I want to show similar rows from my database by a PHP term.
I have a table called "games" and a column called "title" that titles are looks like "Rockstar - GTA V".
So i want to remove all words after dash and use new string as keyword to search in database.
My CMS use this code to show post title inside the loop:
$_smarty_tpl->tpl_vars['game']->value['title']
I just found a code to convert "Rockstar - GTA V" to "Rockstar":
<?php $mygame = strstr($_smarty_tpl->tpl_vars['game']->value['title'], '-', true); echo($mygame); ?>
When i put this code in my "Single template file", it work fine and trim the title as i want and it work good in every game's single page.
So i want to make a section in single page to display all games made by that company (i mean that trimmed word from title). I tried some codes and nothing! This is what i tried:
<?php
$connect = mysqli_connect("localhost", "dbname", "dbpass", "dbuser");
$connect->set_charset('utf8mb4');
mysqli_set_charset($link, 'utf8mb4');
$gamecompany = strstr($_smarty_tpl->tpl_vars['game']->value['title'], '-', true);
$query = 'SELECT * FROM games WHERE title = "'.$gamecompany.'" ORDER BY game_id ASC LIMIT 50';
$result = mysqli_query($connect, $query);
if(mysqli_num_rows($result) > 0)
{
$output .= '<div class="list">';
while($row = mysqli_fetch_array($result))
{
$output .= '<li class="game">'.$row["title"].'</li>';
}
$output .= '</div>';
echo $output;
}
else
{
echo 'Nothing Found';
}
?>
So i used $gamecompany to trim and get a game's company and use it as a keyword in query. But everytime it just show "Nothing Found". When i have some games with keyword "Rockstar" in my database But it won't display that and just pass the conditions statement and can't show nothing.
Tried another keywords (Directly in my code) but won't work!
And one note: My titles are in "Arabic" language and it should be UTF8. Is this my problem? or just a wrong coding?
Using LIKE you can find all occurences with 'Rockstar', but to be safe, convert it to lower case and remove any extra spaces that might occur. Also, lets protect ourselves from SQL attacks with a prepared statement.
$gamecompany = strtolower(trim(strstr($_smarty_tpl->tpl_vars['game']->value['title'], '-', true))); // put it in lower case, trim any excess white space
$query = 'SELECT * FROM games WHERE LOWER(title) LIKE ? ORDER BY game_id ASC LIMIT 50';
$stmt = $conn->prepare($query);
$value = "%$gamecompany%"; // The % allows us to find any titles that have our search string in them
$stmt->bind_param("s", $value);
$stmt->execute();
$result = $stmt->get_result();
For you requirement
title = "'.$gamecompany.'"
is not going to work. You'll need to either use likewise search or full-text search
Likewise
title like '$gamecompany'
Full-Text - For full-text to work, you'll need to have full-text index for that column
MATCH (title) AGAINST (:gamecompany IN NATURAL LANGUAGE MODE)
You can create Full-text index like this
ALTER TABLE games ADD FULLTEXT(title)
Try using the LIKE keyword inside the query , and for the Arabic part make sure both the web app and the database uses the same encoding , i once had this problem and when both of them followed the same encode it worked out.

The search box on my website always search only for the last words of the entered sentence

I recently added search box to search certain data on my database.
Im using php LIKE function.for the first time when i use LIKE function it took only one word and if that match any of contents then the results came out.and if i type more than one word it came zero results and it return a error that "No results".
And as i did a research i made my code it to thing.(Now it is allways searching only for the last word on the sentence that we enter for search.)]
In a example :
If type "car for sell" the query going to search for "Sell" .If there are any records match the query then it will exicutue (weather it is car or any other data.)
what i want to do iss to let it search for complete search where it matchs in the database.
For a example :
if i want to find "car for sell"
i want the query to execute only cars for sell in my cars category and so on.
here are my codes.
$getquery = $_GET['query'];
if(isset($_GET['query'])){
$getquery = $_GET['query'];
$queryexplode = explode(" ", $getquery);
foreach($queryexplode as $queryexplodenew){
$meta = $queryexplodenew;
}
$getdataquery = "SELECT `AdName`, `AdAccessLink`, `timestamp`, `Country`, `Category`, `Price`, `Photo1name` FROM freeadpostingdata WHERE AdName LIKE '%$queryexplodenew%' OR Country LIKE '%$queryexplodenew%' OR Category LIKE '%$queryexplodenew%' OR AdDescription LIKE '%$queryexplodenew%' ORDER BY timestamp DESC LIMIT 0, 25";
$resultsgetdata = mysql_query($getdataquery);
$countprodu= mysql_num_rows($resultsgetdata);
}
please help me to get this solved.
thank you
The reason you are only searching for the last word is because of this:
$queryexplode = explode(" ", $getquery);
foreach($queryexplode as $queryexplodenew){
$meta = $queryexplodenew;
}
You are iterating over each word in the query with each word being put in $queryexplodenew in turn (and then assigned to $meta for some reason). When the loop completes, the thing in $queryexplodenew will be the last element iterated over.
Yes, for your code, it will always search for the last word.
$getquery = $_GET['query'];
$modifiedKeyword = explode(" ", $getquery);
$str = implode("', '", $modifiedKeyword );
And change your query like the following:
$sql = "SELECT id FROM your_table WHERE keyword IN ('$str')";
I hope it will work for you.

MySQL query that can handle missing characters

I'm trying to improve my MySQL query.
SELECT gamename
FROM giveaway
WHERE gamename LIKE '$query'
I got an input that consists of URL's that are formed like:
http://www.steamgifts.com/giveaway/l7Jlj/plain-sight
http://www.steamgifts.com/giveaway/okjzc/tex-murphy-martian-memorandum
http://www.steamgifts.com/giveaway/RqIqD/flyn
http://www.steamgifts.com/giveaway/FzJBC/penguins-arena-sednas-world
I take the game name from the URL and use this as input for a SQL query.
$query = "plain sight"
$query = "tex murphy martian memorandum"
$query = "flyn"
$query = "penguins arena sednas world"
Now in the database the matching name sometimes has more characters like : ' !, etc.
Example:
"Plain Sight"
"Tex Murphy: Martian Memorandum"
"Fly'N"
"Penguins Arena: Sedna's World!"
So when putting in the acquired name from the URL this doesn't produce results for the 2nd, 3rd and 4th example.
So what I did was use a % character.
$query = "plain%sight"
$query = "tex%murphy%martian%memorandum"
$query = "flyn"
$query = "penguins%arena%sednas%world"
This now gives result on the 1st and 2nd example.
.
On to my question:
My question is, how to better improve this so that also the 3rd and 4th ones work?
I'm thinking about adding extra % before and after each character:
$query = "%f%l%y%n%"
$query = "%p%e%n%g%u%i%n%s%a%r%e%n%a%s%e%d%n%a%s%w%o%r%l%d%"
But I'm not sure how that would go performance wise and if this is the best solution for it.
Is adding % a good solution?
Any other tips on how to make a good working query?
Progress:
After a bit of testing I found that adding lots of wildcards (%) is not a good idea. You will get returned unexpected results from the database, simply because you just added a lot of ways things could match.
Using the slug method seems to be the only option.
If i get your question well, you are creating a way of searching through those informations. And if that is the case then try
$query = addslashes($query);
SELECT name
FROM giveaway
WHERE gamename LIKE '%$query%'
Now if you want to enlarge your search and search for every single word that looks like the words in your string, then you can explode the text and search for each word by doing
<?php
$query = addslashes($query);
//We explode the query into a table
$tableau=explode(' ',$query);
$compter_tableau=count($tableau);
//We prepare the query
$req_search = "SELECT name FROM giveaway WHERE ";
//we add the percentage sign and the combine each query
for ($i = 0; $i < $compter_tableau; $i++)
{
$notremotchercher=$tableau["$i"];
if($i==$compter_tableau) { $liaison="AND"; } else { $liaison=""; }
if($i!=0) { $debutliaison="AND"; } else { $debutliaison=""; }
$req_search .= "$debutliaison gamename LIKE '%$notremotchercher%' $liaison ";
}
//Now you lauch your query here
$selection=mysqli_query($link, "$req_search") or die(mysqli_error($link));
?>
By so doing you would have added the % to every word in your query which will give you more result that you can choose from.

Autocomplete search query mysql

I'm having trouble with a search query.
I have two columns named 'artist' & 'title'. But for an autocomplete function I need a SQL query to search in these columns while someone is typing. There is a very simple solution I know of which is the following:
SELECT * FROM music WHERE artist LIKE '%".$term."%' OR title LIKE
'%".$term."%'
$term = textboxvalue
But this query has a couple of huge problems. Let's say the artist is 'DJ Test' and the title is 'Amazing Test Song'. If I type 'DJ' it works fine. But when I type 'DJ Amazing'. No search results were found. Obviously ofcourse but I can't figure how to fix it.
But that's not the only problem. If someone types in 'DJ Test - Amazing Test Song' it has to ignore the '-'.
So my question is, what does my search query look like when I can type anything like 'Amazing DJ Test' and still give back what I need?
Try something like this.
I think it should work but I haven't tested it.
$terms = explode(' ', $term);
foreach($terms as $term){
$query = SELECT * FROM music WHERE artist LIKE '%".$term."%' OR title LIKE '%".$term."%'
return $query;
}
Should hopefully work
You would have to make it split the search string up into words, then add those words as lookup criteria by appending them to the query.
First make an array that contains each individual word from the search string.
$search = 'DJ TEST Amazing Test Song';
$search_terms = explode(" ", $search);
Then alter the query for each search term:
foreach($search_terms as $search_term) {
//append OR to query with $search_term
$query .= "OR artist LIKE '%".$search_term."%' OR title LIKE '%".$search_term."%'";
}

prevent sql injection on query with variable (and large) number of columns

I have a sql query that is generated using php. It returns the surrogate key of any record that has fields matching the search term as well as any record that has related records in other tables matching the search term.
I join the tables into one then use a separate function to retrieve a list of the columns contained in the tables (I want to allow additions to tables without re-writing php code to lower ongoing maintenance).
Then use this code
foreach ($col_array as $cur_col) {
foreach ($search_terms_array as $term_searching) {
$qry_string.="UPPER(";
$qry_string.=$cur_col;
$qry_string.=") like '%";
$qry_string.=strtoupper($term_searching);
$qry_string.="%' or ";
}
}
To generate the rest of the query string
select tbl_sub_model.sub_model_sk from tbl_sub_model inner join [about 10 other tables]
where [much code removed] or UPPER(tbl_model.image_id) like '%HONDA%' or
UPPER(tbl_model.image_id) like '%ACCORD%' or UPPER(tbl_badge.sub_model_sk) like '%HONDA%'
or UPPER(tbl_badge.sub_model_sk) like '%ACCORD%' or UPPER(tbl_badge.badge) like '%HONDA%'
or UPPER(tbl_badge.badge) like '%ACCORD%' group by tbl_sub_model.sub_model_sk
It does what I want it to do however it is vulnerable to sql injection. I have been replacing my mysql_* code with pdo to prevent that but how I'm going to secure this one is beyond me.
So my question is, how do I search all these tables in a secure fashion?
Here is a solution that asks the database to uppercase the search terms and also to adorn them with '%' wildcards:
$parameters = array();
$conditions = array();
foreach ($col_array as $cur_col) {
foreach ($search_terms_array as $term_searching) {
$conditions[] = "UPPER( $cur_col ) LIKE CONCAT('%', UPPER(?), '%')";
$parameters[] = $term_searching;
}
}
$STH = $DBH->prepare('SELECT fields FROM tbl WHERE ' . implode(' OR ', $conditions));
$STH->execute($parameters);
Notes:
We let MySQL call UPPER() on the user's search term, rather than having PHP call strtoupper()
That should limit possible hilarious/confounding mismatched character set issues. All your normalization happens in one place, and as close as possible to the moment of use.
CONCAT() is MySQL-specific
However, as you tagged the question [mysql], that's probably not an issue.
This query, like your original query, will defy indexing.
Try something like this using an array to hold parameters. Notice % is added before and after term as LIKE %?% does not work in query string.PHP Manual
//Create array to hold $term_searching
$data = array();
foreach ($col_array as $cur_col) {
foreach ($search_terms_array as $term_searching) {
$item = "%".strtoupper($term_searching)."%";//LIKE %?% does not work
array_push($data,$item)
$qry_string.="UPPER(";
$qry_string.=$cur_col;
$qry_string.=") LIKE ? OR";
}
}
$qry_string = substr($qry_string, 0, -3);//Added to remove last OR
$STH = $DBH->prepare("SELECT fields FROM table WHERE ". $qry_string);//prepare added
$STH->execute($data);
EDIT
$qry_string = substr($qry_string, 0, -3) added to remove last occurrence of OR and prepare added to $STH = $DBH->prepare("SElECT fields FROM table WHERE". $qry_string)

Categories