I have a problem, I wanted to make a query to the search form data where people insert some filters will search for products appear less in this specific case are houses.
had made a query with "or" does not work as well as this it makes the fields alone, and "and" not also works because I do not want users to fill out all the fields, so is the they want, so I did it
$texto = array();
$contador=0;
if($_SESSION["finalidade"]!=""){
$contador++;
$texto[1]="`finalidade` LIKE ".$finalidade;}
if($_SESSION["tipoimovel"]!=""){
$contador++;
$texto[2]="`tipoimovel` LIKE ".$tipoimovel;}
if($_SESSION["nquarto"]!=0){
$contador++;
$texto[3]="`nquartos` = ".$nquarto;}
if($_SESSION["pmin"]!=0){
$contador++;
$texto[4]="`preco` > ".$pmin;}
if($_SESSION["pmax"]!=0){
$contador++;
$texto[5]="`preco` < ".$pmax;}
if($_SESSION["elevador"]!=""){
$contador++;
$texto[6]="`elevador` LIKE ".$elevador;}
if($_SESSION["garagem"]!=""){
$contador++;
$texto[7]="`garagem` LIKE ".$garagem;}
if($_SESSION["vistapriv"]!=""){
$contador++;
$texto[8]="`vistapreveligiada` LIKE ".$vistapriv;}
if($_SESSION["piscina"]!=""){
$contador++;
$texto[9]="`piscina` LIKE ".$piscina;}
if($_SESSION["jardim"]!=""){
$contador++;
$texto[10]="`jardim` LIKE ".$jardim;}
if($_SESSION["condominiof"]!=""){
$contador++;
$texto[11]="`condominio` LIKE ".$condominiof;}
if($_SESSION["conselho"]!=""){
$contador++;
$texto[12]="`conselho` LIKE ".$conselho;}
if($_SESSION["frequesia"]!=""){
$contador++;
$texto[13]="`frequesia` LIKE ".$frequesia;}
if($_SESSION["refimovel"]!=""){
$contador++;
$texto[14]="`referencia` LIKE ".$refimovel;}
$textocompleto="";
$contador2=1;
for($y = 0; $y < 16; $y++) {
if($texto[$y]!=""){
if($contador2==1 && $contador2!=$contador){
$contador2++;
;
$textocompleto=$texto[$y]." AND "; }
elseif($contador2==$contador){
$contador2++;
$textocompleto=$textocompleto.$texto[$y];}
elseif($contador2==1 && $contador2==$contador){
$contador2++;
$textocompleto=$texto[$y]; }
else {
$contador2++;
$textocompleto=$textocompleto.$texto[$y]." AND ";}
}
}
$results = $mysqli->prepare("SELECT ID, imagem, frequesia ,conselho, preco FROM `imovel` WHERE ? ORDER BY `imovel`.`preco` DESC LIMIT ?,? ");
$results->bind_param("sii",$textocompleto, $page_position, $item_per_page);
$results->execute();
$results->bind_result($id ,$imagem, $frequesia ,$conselho, $preco); //bind variables to prepared statement
}
the problem is that it is not me to return anything, does not show me any value.
already do not know what else to do because if you make a if for each of the possibilities will give more than 100 if and will take a long time.
if anyone knows of some effective and quick way to do this please help me, because in fact not know what else to do to fix this problem, thank you
You cannot bind parts of an SQL statement, you can only bind values.
So this is valid:
$results = $mysqli->prepare("SELECT col1, col2 FROM tbl WHERE col3 = ?");
$results->bind_param("i", 1234);
and this is not:
$results = $mysqli->prepare("SELECT col1, col2 FROM tbl WHERE ?");
$results->bind_param("s", "col3 = 1234");
You can concatenate the strings, though:
prepare("SELECT ... WHERE ".$textocompleto." ORDER BY imovel.preco DESC LIMIT ?,? ");
You can use a prefix on your $\_SESSION variable like sf_{variable_name} for all required fields. After that, you can loop throughout them to build your query
(ps : code not tested):
$sql = "SELECT ";
$sql_cond = " WHERE ";
$texto = [];
foreach($_SESSION as $k => $v){
if(substr($v, 0, 3) == "sf_"){
$name = substr($k, 3, strlen($k))
$texto[$name] = $v;
$sql .= $name.", ";
$sql_cond .= $name." LIKE :".$name;
}
}
$final_sql = $sql.$sql_cond;
$results = $mysqli->prepare($final_sql);
foreach($texto as $k => $v){
$results->bind_param(":".$k, "%".$v."%");
}
$results->execute();
Ok, after some tests, i did the same with PDO object in a test db for medias (PDO is nearly the same stuff than MYSQLI object), and it work fine for me, just adapt your db ids for your case
$pdo = new PDO('mysql:host=localhost;dbname=media_center', 'root', 'root');
$_SESSION["sf_title"] = "Interstellar";
$_SESSION["sf_description"] = "sci-fi";
$sql = "SELECT * ";
$sql_cond = " WHERE ";
$texto = [];
foreach($_SESSION as $k => $v){
if(substr($k, 0, 3) == "sf_"){
$name = substr($k, 3, strlen($k));
$texto[$name] = $v;
$sql_cond .= $name." LIKE :".$name." OR ";
}
}
$sql_cond = substr($sql_cond, 0, strlen($sql_cond)-4);
$final_sql = $sql." FROM media ".$sql_cond;
$results = $pdo->prepare($final_sql);
foreach($texto as $k => $v){
$key = ":".$k;
$value = "%".$v."%";
$results->bindParam($key, $value);
}
$results->execute();
I guess you will need to wrap the values in single qoute ''
For example:
$texto[1]="`finalidade` LIKE ".$finalidade;
should be
$texto[1]="`finalidade` LIKE '".$finalidade."'";
Try this.. I think it will solve it
Related
I'm trying to build a MySQL search to match keywords occurring in any order in the column being searched (not just whole phrases as would normally be the case). My class function is:
public function keywords_author($keywords, $author) {
$keywords = explode(" ", trim($keywords));
$keywords = array_filter($keywords);
$count_keywords = count($keywords);
if ($count_keywords != 0) {
$query = "SELECT * FROM `table` WHERE ";
$query_echo = $query;
$a = 0;
while ($a < $count_keywords) {
$query .= "`column` LIKE :keyword ";
$query_echo .= "`column` LIKE '%" . $keywords[$a] . "%' ";
$a++;
if ($a < $count_keywords) {
$query .= " && ";
$query_echo .= " && ";
}
}
$stmt = $this->db->prepare($query);
for ($a=0; $a<$count_keywords; $a++) {
$keyword = "%" . $keywords[$a] . "%";
$stmt->bindParam(':keyword', $keyword);
}
$stmt->execute();
$output = '';
while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
// build $output
}
echo $output;
echo $query_echo;
}
}
I have just added $query_echo to check the query being built, which is:
SELECT * FROM `table`
WHERE `column` LIKE '%php%'
&& title LIKE '%mysql%'
&& title LIKE '%jquery%'
&& title LIKE '%ajax%'
This works fine when I copy that into the SQL command line in phpMyAdmin, returning only those records where ALL keywords are matched, but when I run the class file in my site it behaves like an OR select and returns results where ANY of the keywords occurs in the column.
I'm confused! Any ideas what's going on would be a huge help!
David -
Thanks, David Kmenta - that's certainly a step in the right direction and now I'm getting the correct query:
SELECT * FROM table WHERE column LIKE :keyword0 AND column LIKE :keyword1 AND column LIKE :keyword2 AND column LIKE :keyword3 AND column LIKE :keyword4
But it is still returning the result for the last value only. I am sure it is a basic, probably obvious error in the loop enclosing the new bindParam statement:
for ($a=0; $a<$count_keywords; $a++) {
$keyword = "%" . $keywords[$a] . "%";
$stmt->bindParam(':keyword'.$a, $keyword);
}
I'm very tired - can you spot the problem?
But
Problem is probably here:
for ($a=0; $a<$count_keywords; $a++) {
$keyword = "%" . $keywords[$a] . "%";
$stmt->bindParam(':keyword', $keyword);
}
Every occurrence of :keyword is replaced with last item in $keywords array.
So I have some data coming in via POST from a form with a large number of checkboxes and I'm trying to find records in the database that match the options checked. There are four sets of checkboxes, each being sent as an array. Each set of checkboxes represents a single column in the database and the values from the checked boxes are stored as a comma-delimited string. The values I'm searching for will not necessarily be consecutive so rather than a single LIKE %value% I think I have to break it up into a series of LIKE statements joined with AND. Here's what I've got:
$query = "";
$i = 1;
$vals = [];
foreach($_POST["category"] as $val){
$query .= "category LIKE :cat".$i." AND ";
$vals[":cat".$i] = "%".$val."%";
$i++;
}
$i = 1;
foreach($_POST["player"] as $val){
$query .= "player LIKE :plyr".$i." AND ";
$vals[":plyr".$i] = "%".$val."%";
$i++;
}
$i = 1;
foreach($_POST["instrument"] as $val){
$query .= "instrument LIKE :inst".$i." AND ";
$vals[":inst".$i] = "%".$val."%";
$i++;
}
$i = 1;
foreach($_POST["material"] as $val){
$query .= "material LIKE :mat".$i." AND ";
$vals[":mat".$i] = "%".$val."%";
$i++;
}
$query = rtrim($query, " AND ");
$tubas = R::convertToBeans("tuba", R::getAll("SELECT * FROM tuba WHERE ".$query, $vals));
This does seem to work in my preliminary testing but is it the best way to do it? Will it be safe from SQL injection?
Thanks!
As long as you use parameterized queries (like you do), you should be safe from SQL injection. There are edge cases though, using UTF-7 PDO is vulnerable (I think redbean is based on PDO)
I would change the code to something like this, minimizes the foreach clutter.
$query = 'SELECT * FROM tuba';
$where = [];
$params = [];
$checkboxes = [
'category',
'player',
'instrument',
'material'
];
foreach ($checkboxes as $checkbox) {
if (!isset($_POST[$checkbox])) {
// no checkboxes of this type submitted, move on
continue;
}
foreach ($_POST[$checkbox] as $val) {
$where[] = $checkbox . ' LIKE ?';
$params[] = '%' . $val . '%';
}
}
$query .= ' WHERE ' . implode($where, ' AND ');
$tubas = R::convertToBeans('tuba', R::getAll($query, $params));
CODE :
$nerd_result = mysql_query("select * from nerd_profile where nerd_reg_no = '$reg_no'");
$nerd_data = mysql_fetch_array($nerd_result);
$tags = array();
$tags = explode(",",$nerd_data['nerd_interests']);
for($i = 0; $i < sizeof($tags)-1; $i++)
{
if($i != sizeof($tags)-2)
{
$sub_query = $sub_query."`tags` like %".$tags[$i]."% or ";
}
else
{
$sub_query = $sub_query."`tags` like %".$tags[$i]."% ";
}
}
$proper_query = "select * from `qas_posts` where ".$sub_query." and `post_date` like '%$today%'";
$result = mysql_query($proper_query);
while($each_qas = mysql_fetch_array($result))
Description :
I am adding the like clause along with php variable in a string and concatenating it with the further variables with like clause to come. In the end when I echo I get the perfect query that I want but
mysql_fetch_array()
does not accept that generated query rather if I hard code it , it works perfect what am I doing wrong ?? can I do that ??
When doing string comparisons in mysql you need to make sure you have quotes around your comparison value.
$sub_query = $sub_query."`tags` like '%".$tags[$i]."%' or ";
and
$sub_query = $sub_query."`tags` like '%".$tags[$i]."%' ";
When I run the following MySQL query via PHP and all of the elements of $_GET() are empty strings, all the records in the volunteers table are returned (for obvious reasons).
$first = $_GET['FirstName'];
$last = $_GET['LastName'];
$middle = $_GET['MI'];
$query = "SELECT * FROM volunteers WHERE 0=0";
if ($first){
$query .= " AND first like '$first%'";
}
if ($middle){
$query .= " AND mi like '$middle%'";
}
if ($last){
$query .= " AND last like '$last%'";
}
$result = mysql_query($query);
What is the most elegant way of allowing empty parameters to be sent to this script with the result being that an empty $result is returned?
my solution:
$input = Array(
'FirstName' => 'first',
'LastName' => 'last',
'MI' => 'mi'
);
$where = Array();
foreach($input as $key => $column) {
$value = trim(mysql_escape_string($_GET[$key]));
if($value) $where[] = "`$column` like '$value%'";
}
if(count($where)) {
$query = "SELECT * FROM volunteers WHERE ".join(" AND ", $where);
$result = mysql_query($query);
}
There's no point in running a (potentially) expensive query if there's nothing for that query to do. So instead of trying to come up with an alternate query to prevent no-terms being searched, just don't run the search at all if there's no terms:
$where = '';
... add clauses ...
if ($where !== '') {
$sql = "SELECT ... WHERE $where";
... do query ...
} else {
die("You didn't enter any search terms");
}
With your current code, if everything is empty, you will get the WHERE 0=0 SQL which is TRUE for all rows in the table.
All you have to do is remove the if statements...
Using PHP on my website linking to a library database in MySQL. The one area I can't seem to get right is the pagination of results. I've tried about twenty different code snippets and have the same problem each time - can't get more than the first page of results to display. Despite reading lots of forum posts on this one, can't get past it. My select query is slightly more complex in that several keywords can be combined and it is searching multiple fields. When results are displayed, they also pull data from different tables. I really hope someone can spot where I'm going wrong. Switch statement used dependent on which type of search the user requests, so the code for one case given below.
$term = trim($_REQUEST['term']);
$searchterm = mysql_real_escape_string($term, $link);
$index = $_REQUEST['index'];
switch ($index)
{
case "title":
$array = explode(" ", $searchterm);
$sql = "select identifier, title, publication_date from publication where";
foreach ($array as $key => $keyword) {
$sql .= " (title like '%$keyword%' or alternative_title like '%$keyword%')";
if ($key != (sizeof($array) - 1)) $sql .= " and ";
if ($key == (sizeof($array) - 1)) $sql .= " order by title";
}
if(!$result = mysql_query($sql, $link)) {
showerror();
}
else {
$numrows = mysql_num_rows($result);
if ($numrows == 0) {
echo "<h2>No records found</h2>";
}
//start pagination
$perPage = 10;
$page = (isset($_REQUEST['page'])) ? (int)$_REQUEST['page'] : 1;
$startAt = $perPage * ($page - 1);
$totalPages = ceil($numrows / $perPage);
$links = "";
for ($i = 1; $i <= $totalPages; $i++) {
$links .= ($i != $page ) ? " <a href='search.php?page=$i&search=$term'>
Page $i</a> " : "$page ";
}
echo "<h3>Displaying page $page of $totalPages:</h3><br />";
$counter = 1;
$sql = "select identifier, title, publication_date from publication where";
foreach ($array as $key => $keyword) {
$sql .= " (title like '%$keyword%' or alternative_title like '%$keyword%')";
if ($key != (sizeof($array) - 1)) $sql .= " and ";
if ($key == (sizeof($array) - 1)) $sql .= " order by title
LIMIT $startAt, $perPage";
}
$result = mysql_query($sql, $link);
echo "<table class=\"results\">\n";
while($row = mysql_fetch_array($result))
{
//echo data
}
echo "</table><br />\n";
echo $links; // show links to other pages
echo "<p> </p>";
}
break;
as stated above, -1 vote for placing someone elses code instead of trying it yourself. This code is wayyyy to much for what a pagination script should do. You could have added more specific code snippet and a better question. I'll try to take a look at it however.
As you can't get further than page 1 it seems that somethings going wrong aroung $page = (isset($_REQUEST['page'])) ? (int)$_REQUEST['page'] : 1 ; or a little below. Try echoƫing your SQL code for each page and take a look if the LIMIT is right or that it stays the same, probably the last. At least that gives you a starting point from where to take a look in your code.
Does it give you the right amount of links to go to?