I want to do a search in a table with search words defined by a user.
I'm doing this by splitting the string an constructing the sql.
But i can't seem to make it work. It works fine, if only one word is entered, but with two or more words it's crashing.
$q = $_GET['q']; //Search word
$q = htmlspecialchars($q);
$q_exploded = explode ( " ", $q );
foreach( $q_exploded as $search_each ) {
$where .= "content LIKE ? OR ";
$bind .= "s";
$param .= "%$search_each%, ";
}
$where = rtrim($where,'OR ');
$param = rtrim($param,', ');
$sql = "SELECT ads_id FROM search_index WHERE ".$where."";
echo $sql . "<br>".$param."<br>".$bind."<br>";
$stmt = $dbconn->prepare($sql);
$stmt->bind_param($bind, $param);
$stmt->execute();
$result = $stmt->get_result();
while ($row = $result->fetch_assoc()) {
echo $row['ads_id'];
}
This is my error
SELECT ads_id FROM search_index WHERE content LIKE ? OR content LIKE ?
%word1%, %word2%
ss
Warning: mysqli_stmt::bind_param(): Number of elements in type
definition string doesn't match number of bind variables
You issue is here:
$stmt->bind_param($bind, $param);
What you're doing is:
$stmt->bind_param("ss", $param);
While you may intend param to satisfy both of the strings it doesn't you need to pass a variable for each one. I would try looking into explode for this.
Someone posted an answer earlier, but deleted it again. That answer actually worked, i just needed to change from mySQLi to DPO.
Solution:
$q = htmlspecialchars($q);
$q_exploded = explode ( " ", $q );
$where = [];
$bind = [];
foreach ($q_exploded as $idx => $search_each) {
$key = ':val' . $idx;
$where[] = "content LIKE " . $key;
$bind[$key] = "%$search_each%";
}
$sql = "SELECT ads_id FROM search_index WHERE " . implode(" OR ", $where);
$stmt = $pdo_conn->prepare($sql);
$stmt->execute($bind);
$result = $stmt->setFetchMode(PDO::FETCH_ASSOC);
while ($row = $stmt->fetch()) {
echo $row['ads_id'] . "<br>";
}
Related
I am trying to make a search script that searches cars in a database and matches ALL keywords input by user. If I leave keywords text box empty and search I get results but if I input any keywords I get no results.
$search_keywords = $_POST['search_keywords'];
$terms = $search_keywords;
$items = explode(' ',$terms);
$types = array();
foreach ($items as $item) {
$types[] = "'title' LIKE '%{$item}%'";
$types[] = "'exterior_colour' LIKE '%{$item}%'";
}
$sql = "SELECT * FROM list_car WHERE ";
$sql .= implode(" && ", $types) . " ORDER BY 'title'";
$result = mysqli_query($link, getPagingQuery($sql, $rowsPerPage));
UPDATE:
Works now i have changed it but if i search Toyota hilux dfkjodsgfudsugfdsgfgfgfdgfdg all the Toyota hilux will appear but dfkjodsgfudsugfdsgfgfgfdgfdg is garbage which is not listed in the database i want it to match ALL keywords not just one or more.
$search_keywords = $_POST['search_keywords'];
$terms = $search_keywords;
$items = explode(' ',$terms);
$types = array();
foreach ($items as $item) {
$types[] = "`title` LIKE '%{$item}%'";
$types[] = "`exterior_colour` LIKE '%{$item}%'";
}
$sql = "SELECT * FROM list_CAR WHERE ";
$sql .= implode(" || ", $types) . "";
$result = mysqli_query($link, getPagingQuery($sql, $rowsPerPage)) or die(mysqli_error($link));
You should use OR (||) instead of AND (&&) . As it is, your search term must match against all fields:
$sql = "SELECT * FROM list_car WHERE ";
$sql .= implode(" OR ", $types) . " ORDER BY 'title'";
Here's how I'd do it.
$terms = $search_keywords = 'Toyota hilux dfkjodsgfudsugfdsgfgfgfdgfdg';
$items = explode(' ',$terms);
$types = array();
$sql = "SELECT * FROM list_CAR WHERE ";
foreach ($items as $item) {
$sql .= " (`title` LIKE ? or `exterior_colour` LIKE ?) and ";
$params[] = '%' . $item . '%';
$params[] = '%' . $item . '%';
}
if(!empty($params)) {
$sql = rtrim($sql, ' and ');
$result = mysqli_prepare($link, $sql);
foreach($params as $param) {
mysqli_stmt_bind_param($result, "s", $param);
}
mysqli_stmt_execute($result);
} else {
die('No params built...WHY');
}
Note I'm using untested mysqli prepared statements, I haven't built the parameterized queries procedurally in mysqli, I base this approach off user comments on the manual's page.
This should give a query such as
SELECT * FROM list_CAR
WHERE
(`title` LIKE ? or `exterior_colour` LIKE ?) and
(`title` LIKE ? or `exterior_colour` LIKE ?) and
(`title` LIKE ? or `exterior_colour` LIKE ?)
Which will require each keyword is present in the title or the color list.
If you were to keep it unprepared, which is unrecommended and poor practice, it would be..
$terms = $search_keywords = 'Toyota hilux dfkjodsgfudsugfdsgfgfgfdgfdg';
$items = explode(' ',$terms);
$types = array();
foreach ($items as $item) {
$types[] = " (`title` LIKE '%{$item}%' or `exterior_colour` LIKE '%{$item}%') ";
}
$sql = "SELECT * FROM list_CAR WHERE ";
$sql .= implode(" and ", $types) . "";
echo $sql;
Output:
SELECT * FROM list_CAR WHERE
(`title` LIKE '%Toyota%' or `exterior_colour` LIKE '%Toyota%') and
(`title` LIKE '%hilux%' or `exterior_colour` LIKE '%hilux%') and
(`title` LIKE '%dfkjodsgfudsugfdsgfgfgfdgfdg%' or `exterior_colour` LIKE '%dfkjodsgfudsugfdsgfgfgfdgfdg%')
Below is my query:
$key = array(1,2);
$in = join(',', array_fill(0, count($key), '?'));
$statement = $pdo->prepare("SELECT * FROM posts WHERE posts.subid IN (".$in.") AND posts.pricing=? AND posts.Poscode=? ORDER BY posts.Poscode DESC LIMIT 60");
$result = array_merge($key, array($rate,$postcode));
$statement->execute($result);
When I replace $key = array(1,2); with $key = array($key); the query only fetches data for the first ID whereby I assume it converts the array into string.
$key also holds the value 1,2 in an array shown below:
$a=$data['sub'];
$key0=array();
foreach($a as $v=>$k)
{
$key0[]=$v;
}
$key2=implode(',',$key0);
$key = array($key2);
How do I make the PDO understand $key holds an array value and not a string?
I solve this problem always using named placeholders. I personally don't like the ? stuff. You need a placeholder for every value of your in.
See the sample code:
$key = array(1,2);
$pricing = "somePricing";
$postcode = "somePostcode";
$bindings = array();
$bindings[] = array(":pricing", $pricing, PDO::PARAM_STR);
$bindings[] = array(":postcode", $postcode, PDO::PARAM_STR);
$key_placeholders = array();
foreach($key as $k => $v) {
$placeholder = ":subid".$k;
$bindings[] = array($placeholder, $v, PDO::PARAM_INT);
$key_placeholders[] = $placeholder;
}
$sql = "SELECT * FROM posts "
. "WHERE posts.subid IN (". implode(",",$key_placeholders).") "
. "AND posts.pricing=:pricing "
. "AND posts.Poscode=:postcode "
. "ORDER BY posts.Poscode "
. "DESC LIMIT 60";
$statement = $pdo->prepare($sql);
foreach($bindings as $b) {
$statement->bindValue($b[0],$b[1],$b[2]);
}
$statement->execute();
Let's say i have and array like this
$array= Array('id'=>'3', 'name'=>'NAME', 'age'=>'12');
Keys from this array are name of columns in table and values are value of columns which i need to update.
I want to update the table based on keys and values.
I am using ADODB
Please help me
try this:
$sql = "UPDATE table SET ";
foreach($array as $key=>$value) {
$sql .= $key . " = " . $value . ", ";
}
$sql = trim($sql, ' '); // first trim last space
$sql = trim($sql, ','); // then trim trailing and prefixing commas
and of course the WHERE clause:
$sql .= " WHERE condition = value";
you will get the string:
UPDATE table SET id = 3, name = NAME, age = 12 WHERE condition = value
L.E: You might need to add apostrophes to strings so I have to change my code to something like this:
$sql = "UPDATE table SET ";
foreach($array as $key=>$value) {
if(is_numeric($value))
$sql .= $key . " = " . $value . ", ";
else
$sql .= $key . " = " . "'" . $value . "'" . ", ";
}
$sql = trim($sql, ' '); // first trim last space
$sql = trim($sql, ','); // then trim trailing and prefixing commas
$sql .= " WHERE condition = value";
which will produce this:
UPDATE table SET id = 3, name = 'NAME', age = 12 WHERE condition = value
L.E 2: If you want the id column in your condition, the code becomes this:
$sql = "UPDATE table SET ";
foreach($array as $key=>$value) {
if($key == 'id'){
$sql_condition = " WHERE " . $key . " = " . $value;
continue;
}
if(is_numeric($value))
$sql .= $key . " = " . $value . ", ";
else
$sql .= $key . " = " . "'" . $value . "'" . ", ";
}
$sql = trim($sql, ' '); // first trim last space
$sql = trim($sql, ','); // then trim trailing and prefixing commas
$sql .= $sql_condition;
which will produce this result:
UPDATE table SET name = 'NAME', age = 12 WHERE id = 3
Hope this helps! :D
foreach ($update_array as $key => $testimonials) {
$name = mysql_real_escape_string($testimonials->name);
$content = mysql_real_escape_string($testimonials->content);
$id = intval($testimonials->id);
$sql = "UPDATE testimonials SET name='$name', content='$content' WHERE id=$id";
$result = mysql_query($sql);
if ($result === FALSE) {
die(mysql_error());
}
}
Source : https://stackoverflow.com/a/7884331/3793639
Other sources to check.
PHP SQL Update array and Simple UPDATE MySQl table from php array
You could use something like this for achieving that:
foreach($values as $value) {
if(!key_exists($value, $item)) {
return false;
}
$table->{$value} = $items[$value];
}
Assuming that the key index is always id and that adodb can use named placeholders you could do this:
$array = Array('id'=>'3', 'name'=>'NAME', 'age'=>'12');
$set = array();
$data = array();
while(list($key,$value)=each($array)) {
$data[':'.$key] = $value;
if($key!='id') {
$set[] = $key . ' = :' . $key;
// if no placeholders use $set[] = $key . " = '" . database_escape_function($value) . "'";
}
}
$sql = "UPDATE table SET ".implode($set, ',')." WHERE id=:id";
//$data is now Array(':id'=>'3', ':name'=>'NAME', ':age'=>'12');
//$sql is now "UPDATE table SET name=:name, age=:age WHERE id=:id";
$stmt = $DB->Prepare($sql);
$stmt = $DB->Execute($stmt, $data);
This is probably the shortest and easiest for you, you can also use something like this to achieve it:
$array = Array('id'=>'3', 'name'=>'NAME', 'age'=>'12');
$sql = "UPDATE table SET ";
$sql .= implode(', ', array_map(function($key, $value){
return is_numeric($value) ? "{$key} = {$value}" : "{$key} = '". mysql_real_escape_string($value). "'";
}, array_keys($array), $array));
$sql .= " WHERE id = 123";
// Result : UPDATE table SET id = 3, name = 'NAME', age = 12 WHERE id = 123
I would like to add " AND " in between the key and value pair arguments for my sql query but I don't know how. I have tried search the net but unable to find a solution.
$cdatahome = fetchCategory(array("status"=>"1","home"=>"1"));
function fetchCategory(array $conditions){
$db = Core::getInstance();
$sql = "SELECT id, title FROM ruj_category WHERE ";
$params = array();
foreach ($conditions as $column => $value) {
if (preg_match('/^[a-z-.]+$/', $column)) {
$sql .= "$column = ?";
$params[] = $value;
}
}
$sql .= " order by title asc";
$res = $db->dbh->prepare($sql);
$res->execute(array_values($params));
$res = $res->fetchAll(PDO::FETCH_ASSOC);
return $res;
$where = array();
foreach ($conditions as $column => $value) {
if (preg_match('/^[a-z-.]+$/', $column)) {
$where[] = "$column = ?";
$params[] = $value;
}
}
$sql .= implode(' AND ', $where);
$cdatahome = fetchCategory(array("status"=>"1","home"=>"1"));
function fetchCategory(array $conditions){
$db = Core::getInstance();
$sql = "SELECT id, title FROM ruj_category WHERE ";
$params = array();
$i = 0;
foreach ($conditions as $column => $value) {
if (preg_match('/^[a-z-.]+$/', $column)) {
if($i != 0){
$sql .= ' AND ';
}
$sql .= "$column = ?";
$params[] = $value;
$i++;
}
}
$sql .= " order by title asc";
$res = $db->dbh->prepare($sql);
$res->execute(array_values($params));
$res = $res->fetchAll(PDO::FETCH_ASSOC);
return $res;
Usually, when I want to put something like AND or & (in the case of URLs), I create an array and implode it on the string I want in the middle. For example:
$items = array("a", "b", "c");
$output = implode(" AND ", $items);
Outputs:
"a AND b AND c"
In your case, you can do your foreach loop to build the string pieces and then use AND as glue in the implode() function as listed out by the second answer.
First, you could put the conditions into an array, as you do with the values to $params. Like $cond[]="$column = ?" and then $sql.=implode(' AND ',$cond);
To have it solved in your foreach: before the loop set $first=false; and in the loop do $sql.=($first?'':' AND ')."$column = ?"; $first=false;
I'm attempting the modify this Modx Snippet so that it will accept multiple values being returned from the db instead of the default one.
tvTags, by default, was only meant to be set to one variable. I modified it a bit so that it's exploded into a list of variables. I'd like to query the database for each of these variables and return the tags associated with each. However, I'm having difficulty as I'm fairly new to SQL and PHP.
I plugged in $region and it works, but I'm not really sure how to add in more WHERE clauses for the $countries variable.
Thanks for your help!
if (!function_exists('getTags')) {
function getTags($cIDs, $tvTags, $days) {
global $modx, $parent;
$docTags = array ();
$baspath= $modx->config["base_path"] . "manager/includes";
include_once $baspath . "/tmplvars.format.inc.php";
include_once $baspath . "/tmplvars.commands.inc.php";
if ($days > 0) {
$pub_date = mktime() - $days*24*60*60;
} else {
$pub_date = 0;
}
list($region, $countries) = explode(",", $tvTags);
$tb1 = $modx->getFullTableName("site_tmplvar_contentvalues");
$tb2 = $modx->getFullTableName("site_tmplvars");
$tb_content = $modx->getFullTableName("site_content");
$query = "SELECT stv.name,stc.tmplvarid,stc.contentid,stv.type,stv.display,stv.display_params,stc.value";
$query .= " FROM ".$tb1." stc LEFT JOIN ".$tb2." stv ON stv.id=stc.tmplvarid ";
$query .= " LEFT JOIN $tb_content tb_content ON stc.contentid=tb_content.id ";
$query .= " WHERE stv.name='".$region."' AND stc.contentid IN (".implode($cIDs,",").") ";
$query .= " AND tb_content.pub_date >= '$pub_date' ";
$query .= " AND tb_content.published = 1 ";
$query .= " ORDER BY stc.contentid ASC;";
$rs = $modx->db->query($query);
$tot = $modx->db->getRecordCount($rs);
$resourceArray = array();
for($i=0;$i<$tot;$i++) {
$row = #$modx->fetchRow($rs);
$docTags[$row['contentid']]['tags'] = getTVDisplayFormat($row['name'], $row['value'], $row['display'], $row['display_params'], $row['type'],$row['contentid']);
}
if ($tot != count($cIDs)) {
$query = "SELECT name,type,display,display_params,default_text";
$query .= " FROM $tb2";
$query .= " WHERE name='".$region."' LIMIT 1";
$rs = $modx->db->query($query);
$row = #$modx->fetchRow($rs);
$defaultOutput = getTVDisplayFormat($row['name'], $row['default_text'], $row['display'], $row['display_params'], $row['type'],$row['contentid']);
foreach ($cIDs as $id) {
if (!isset($docTags[$id]['tags'])) {
$docTags[$id]['tags'] = $defaultOutput;
}
}
}
return $docTags;
}
}
You don't add in more WHERE clauses, you use ANDs and ORs in the already existing where clause. I would say after the line $query .= " WHERE stv.name = '".$region... you put in
foreach ($countries as $country)
{
$query .= "OR stv.name = '{$country}', ";
}
but I don't know how you want the query to work.