-3

I am new to php and coding in general.

Until now, my users had to match a perfect formatting when doing a search because the whole string had to be exactly included in the mysql table.

I am trying to split the search string by spaces into an array and then match every array with the search column "itemname". Using my code, I can only search for a single word. The $split[0]; is being searched, if another word is added, no matches will be found.

// Search from MySQL database table
$search=$_POST['search'];
$stat=$_POST['stat'];

$split = explode(" ", $search);

$query = $pdo->prepare("SELECT itemname, itemprice, itemupdate, itemstat, itemmarket, itemdiff FROM premium WHERE itemname LIKE ? AND itemname LIKE ? AND itemname LIKE ? AND itemname LIKE ? AND itemname LIKE ? AND itemname LIKE ? AND itemstat=? ORDER BY itemprice DESC LIMIT 15");
$query->bindValue(1, "%$split[0]%", PDO::PARAM_STR);
$query->bindValue(2, "%$split[1]", PDO::PARAM_STR);
$query->bindValue(3, "%$split[2]", PDO::PARAM_STR);
$query->bindValue(4, "%$split[3]", PDO::PARAM_STR);
$query->bindValue(5, "%$split[4]", PDO::PARAM_STR);
$query->bindValue(6, "%$split[5]", PDO::PARAM_STR);
$query->bindValue(7, $stat);
$query->execute();

A friend of mine changed my code a few days ago to protect me from sql-injections. He added "?" instead of a variable name into the query and changed something about the bindvalue things below the query.

I tried to make the delimiting work by myself, but I think I don't understand my own code good enough. What will I have to change in the query and the lines below and why? I am trying to understand.

And will i have to add each array number by itself? What if a user is searching with a 10-word-long string, but there are only 5 arrays in the query?


Short - What i would like to achieve:

SELECT * FROM premium WHERE itemname LIKE $split[0] and itemname LIKE $split[1] and itemname Like $split[2] ... and so on ...

---

EDIT:

Here is my code, before I tried modified it:

$search=$_POST['search'];
$stat=$_POST['stat'];
$query = $pdo->prepare("SELECT itemname, itemprice, itemupdate, itemstat FROM pricedata WHERE itemname Like ? AND itemstat=? ORDER BY itemprice DESC LIMIT 15");
$query->bindValue(1, "%$search%", PDO::PARAM_STR);
$query->bindValue(2, $stat);
$query->execute();

I actually want to achieve some kind of "AND" search.

How it is: User wants to find "This is an apple tree" - He has to type "is an apple" or "This is an" because his string need to match the result as a whole string.

How it should be: Users should find the same sentence when typing "tree apple" or "this is tree". I'd like to achieve that by splitting up the search string and then check for every word if it matches inside the result. Only results should be found where EVERY word in the search string is present.


EDIT2

Code right now:

// Search from MySQL database table
$search=$_POST['search'];
$stat=$_POST['stat'];
$split = explode(" ", $search);
$query = $pdo->prepare("SELECT itemname, itemprice, itemupdate, itemstat, itemmarket, itemdiff FROM premium WHERE MATCH (itemname) AGAINST (?) ORDER BY itemprice DESC LIMIT 15");
$query->execute(array(implode(' ', $split)));


$sql = "UPDATE `cars` SET `model` = :model WHERE id = :id";
$statement = $pdo->prepare($sql);
Thomas Weiss
  • 375
  • 1
  • 2
  • 16
  • So the code snippet you have posted, with the prepare and bindValue - is that your code or your friend's code? Are you trying to understand what that code does and why is it better than the one under your "short" example? – Extrakun May 02 '16 at 19:31
  • Well, all but the first are missing the `%` at the end... – Niet the Dark Absol May 02 '16 at 19:31
  • how can you be sure `$split` has 6 elements in the array? Enable error reporting – andrew May 02 '16 at 19:32
  • Build the query and bindings dynamically. Also are you asking how to search for individual terms or all terms? If individual use `or`, not `and`. – chris85 May 02 '16 at 19:32
  • (1) The code in my original post is the one I tried to modify but got confused. I will add the one my friend made, which I used for a whilte in a second. (2) The % should be there, that was an accident. (3) I am not sure how many elements split has. If the user enters just 1 word, there should only be one I guess. I will also add something to my original post. – Thomas Weiss May 02 '16 at 19:33

1 Answers1

2

If you want to use the full text search capabilities of mySQL, you could do this:

...
$query = $pdo->prepare("
    SELECT itemname, itemprice, itemupdate, itemstat, itemmarket, itemdiff
    FROM premium
    WHERE MATCH (itemname) AGAINST(?)
    ORDER BY itemprice DESC
    LIMIT 15
");
$query->execute([implode(' ', $split)]);

OR you can do a boolean search with + (must-haves) or - (mustn't-haves) and * (partial word matches). See example for partial must-haves:

$query = $pdo->prepare("
    SELECT itemname, itemprice, itemupdate, itemstat, itemmarket, itemdiff
    FROM premium
    WHERE MATCH (itemname) AGAINST(? IN BOOLEAN MODE)
    ORDER BY itemprice DESC
    LIMIT 15
");
$query->execute(['+'.implode('* +', $split).'*']);

For boolean mode you would have to clean up the just like a, the, etc to actually make it work best. I recommend to read some tutorials about the full-text search and you can implement better sorting and other cool things too.

Quick tip: you will need to full-index the itemname field in your db table.

i--
  • 4,349
  • 2
  • 27
  • 35
  • I visited this link before and couldn't make it work somehow. I really tried. Trying your code it shows an unexpected "[" on the last line ($query->execute([implode(' ', $split)]);" – Thomas Weiss May 02 '16 at 19:47
  • Try `array(implode(' ', $split))` instead of `[implode(' ', $split)]` - [ref](http://stackoverflow.com/questions/17772534/php-difference-between-array-and). – i-- May 02 '16 at 19:49
  • Now it does search, but it doesn't find any matches. – Thomas Weiss May 02 '16 at 19:53
  • @ThomasWeiss, updated the answer for you to account for AND & partial word searches, well and there was one syntax error. – i-- May 03 '16 at 16:03