array is converted as string in PDO - php

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();

Related

PHP prepared SQL with multiple LIKE condition

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>";
}

Search exact keywords

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%')

PHP output array into SELECT mysql

Need to find array, and then run a MYSQL SELECT where array values are present (or not present).
$symbol = "abc";
$sql = "SELECT * FROM around";
$results = $conn->query($sql);
foreach($results as $row) {
$stop = preg_replace("/[0-9]/", "", $row['tip']);
if ($stop == $symbol)
{$sword = $row['tip'];
}}
So we need $sword to serve as an array in the event that there are multiple outputs. After we have that array, we need to run a mysql query that shows only those that have $sword array.
$query = "
SELECT * FROM ms WHERE `big` = '$sword'";
$result = mysql_query( $query );
So then we can do something like:
while ( $row = mysql_fetch_assoc( $result ) ) {
echo '"time": "' . $row['time'] . '",'; }
Here's the code, converting $sword to an array and using it in your 2nd query:
$symbol = array("abc", "def", "ghi");
$sword = array();
$sql = "SELECT * FROM around";
$results = $conn->query($sql);
foreach($results as $row) {
$stop = preg_replace("/[0-9]/", "", $row['tip']);
if (in_array($stop, $symbol)) {
$sword[] = $row['tip'];
}
}
if ($sword) {
$in = '';
$sep = '';
foreach ($sword as $s) {
$in .= "$sep '$s'";
$sep = ',';
}
/* $in now contains a string like "'123abc123', '12abc12', '1abc1'" */
$query = "
SELECT * FROM ms WHERE `big` IN ($in)";
$result = mysql_query( $query );
while ( $row = mysql_fetch_assoc( $result ) ) {
echo '"time": "' . $row['time'] . '",';
}
}
Now I'm going to go wash my hands to get all that mysql_query off me... :-)

creating a function to do standard DELETEs using prepared statments and php

I am currently going through a nettuts.com tutorial on building a twitter clone and there they have a function for deleting rows from a database and they are using the query method but i tried converting the function to a prepared statement.However I get the Invalid parameter number: parameter was not defined error.Here is the code for the function
public function delete($table, $arr){
$query = "DELETE FROM " . $table;
$pref = "WHERE ";
foreach ($arr as $key => $value) {
$query .= $pref. $key . " = " . ":" . $key;
$pref = "AND ";
}
$query .= ";";
$result = $this->db->prepare($query);
$result->execute($arr);
}
$connect = new Model();
$connect->delete("ribbits", array("user_id" => 2,
"ribbit" => "trial ribbit"
));
can someone please tell me what I am doing wrong?Thank you!
When you pass your array to ->execute(), the keys need to have the : character before them (just like they appear in the SQL query).
So, in your delete function, build the SQL query like this:
public function delete($table, $arr){
$keys = array();
$values = array();
foreach($arr as $key => $value){
$keys[] = $key . " = :" . $key;
$values[":".$key] = $value;
}
$query = "DELETE FROM " . $table . " WHERE " . implode(" AND ", $keys);
$result = $this->db->prepare($query);
$result->execute($values);
}

PDO PHP Adding "AND" in BetweenPlaceholders

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;

Categories