Dynamic mysql query in prepared - php

I am creating dynamic query in PHP.
#$id = $_POST[id];
#$field1 = $_POST[field1];
#$field2 = $_POST[field2];
#$field3 = $_POST[field3];
$id = "id";
$field1 = "222";
$field2 = "787";
$field3 = "4444444";
$whereArr = array();
if($id != "") $whereArr[] = "id = {$id}";
if($field1 != "") $whereArr[] = "field1 = {$field1}";
if($field2 != "") $whereArr[] = "field2 = {$field2}";
if($field3 != "") $whereArr[] = "field3 = {$field3}";
$whereStr = implode(" AND ", $whereArr);
$query = "Select * from assignments WHERE {$whereStr}";
echo $query;
It is working fine.
Select * from assignments
WHERE id = id AND field1 = 222 AND field2 = 787 AND field3 = 4444444
I am getting the correct query but mysql is no longer maintained. So, I am using prepared statement like this.
$firstname = 'Patrick';
$lastname = 'Allaert';
$query = 'SELECT * FROM users';
$cond = array();
$params = array();
if (!empty($firstname)) {
$cond[] = "firstname = ?";
$params[] = $firstname;
}
if (!empty($lastname)) {
$cond[] = "lastname = ?";
$params[] = $lastname;
}
if (count($cond)) {
$query .= ' WHERE ' . implode(' AND ', $cond);
}
echo $query;
Problem is how can i bind the parameters.
$stmt->bind_param("sss", $firstname, $lastname, $email);
Thanks for your advise.

You can pass the array into the execute and it will bind the values of that array.
$firstname = 'Patrick';
$lastname = 'Allaert';
$query = 'SELECT * FROM users';
$cond = array();
$params = array();
if (!empty($firstname)) {
$cond[] = "firstname = ?";
$params[] = $firstname;
}
if (!empty($lastname)) {
$cond[] = "lastname = ?";
$params[] = $lastname;
}
if (count($cond)) {
$query .= ' WHERE ' . implode(' AND ', $cond);
}
$stmt = $pdo->prepare($query);
$stmt->execute($params);
You can see this approach on the manual as example #3. http://php.net/manual/en/pdo.prepared-statements.php
Mysqli approach:
$firstname = 'Patrick';
$lastname = 'Allaert';
$query = 'SELECT * FROM users';
$cond = array();
$params = array();
if (!empty($firstname)) {
$cond[] = "firstname = ?";
$params[] = $firstname;
}
if (!empty($lastname)) {
$cond[] = "lastname = ?";
$params[] = $lastname;
}
if (count($cond)) {
$query .= ' WHERE ' . implode(' AND ', $cond);
}
$stmt = $mysqli->prepare($query);
if(!empty($params)) {
$n = count($params);
$a_params[] = & str_repeat('s', $n);
for($i = 0; $i < $n; $i++) {
$a_params[] = & $params[$i];
}
call_user_func_array(array($stmt, 'bind_param'), $a_params);
}
$stmt->execute();
$res = $stmt->get_result();
while($row = $res->fetch_array(MYSQLI_ASSOC)) {
print_r($row);
}

No need for arrays in your script
you can use script like below:
$where = " 1=1";
if($id != "") $where .= " and id = $id ";
if($field1 != "") $where .= " and field1 = '" . $field1 . "' ";
if($field2 != "") $where .= " and field2 = '" . $field2 . "' ";
if($field3 != "") $where .= " and field3 = '" . $field3 . "' ";
$query = "Select * from assignments WHERE $where";
echo $query;

Related

Change SQL Query to a prepared statement with condition

I'm trying to change this query to a query with prepared statement, but I have some problem because of conditions.
This is my basic query :
function ResponseByQuery($link,$idQuery,$Boutique=null, $agency=null){
$from_agence = "";
$req_agence = "";
$req_boutique = "";
if($Boutique!=null){
$req_boutique = " AND C.idUser ='" . $Boutique . "' ";
}
if($agency!=null){
$from_agence = ", infos_client as IRC2";
$req_agence = " AND IRC.idClient = IRC2.idClient
AND IRC2.valueInfo = '". $agency."'";
}
$sql = "SELECT distinct(C.idClient), R.indiceRequete
FROM `infos_client` as IRC, client as C, user as U, requete as R ".$from_agence."
WHERE IRC.idQuery='" . $idQuery . "'".
$req_boutique.
"AND IRC.idCl = C.idCl
AND C.idUser=U.idUser".$req_agence;
$result = mysqli_query($link,$sql) or die("Query (- $sql -) failed");
$count = mysqli_num_rows($result);
}
I changed it to this :
function ResponseByQuery($link,$idQuery,$Boutique=null, $agency=null){
$from_agence = "";
$req_agence = "";
$req_boutique = "";
if($Boutique!=null){
$req_boutique = " AND C.idUser ='" . $Boutique . "' ";
}
if($agency!=null){
$from_agence = ", infos_client as IRC2";
$req_agence = " AND IRC.idClient = IRC2.idClient
AND IRC2.valueInfo = '". $agency."'";
}
$sql = "SELECT distinct(C.idClient), R.indiceRequete
FROM `infos_client` as IRC, client as C, user as U, requete as R ".$from_agence."
WHERE IRC.idQuery =?".
$req_boutique.
"AND IRC.idCl = C.idCl
AND C.idUser=U.idUser".$req_agence;
$stmt = $link->prepare($sql);
$stmt->bind_param('i', $idQuery);
$result = $stmt->execute() or die("Query (- $sql -) failed");
$result = $stmt->get_result();
$count = mysqli_num_rows($result);
}
but I don't know how can I change conditions($req_boutique,$req_agence) to prepared statement?
You can replace the inlined variables in your $req_boutique and $req_agence conditions with placeholders, and then conditionally bind values to them:
if($Boutique!=null){
$req_boutique = " AND C.idUser = ? ";
}
if($agency!=null){
$from_agence = ", infos_client as IRC2";
$req_agence = " AND IRC.idClient = IRC2.idClient
AND IRC2.valueInfo = ? ";
}
$sql = "SELECT distinct(C.idClient), R.indiceRequete
FROM `infos_client` as IRC, client as C, user as U, requete as R ".$from_agence."
WHERE IRC.idQuery =? ".
$req_boutique.
"AND IRC.idCl = C.idCl
AND C.idUser=U.idUser".$req_agence;
$stmt = $link->prepare($sql);
$types = 'i';
$vars = [$idQuery];
if ($Boutique != null) {
$types .= 's';
$vars[] = $Boutique;
}
if ($agency!= null) {
$types .= 's';
$vars[] = $agency;
}
$stmt->bind_param($types, ...$vars);

Updating SQL query from single column single value LIKE to multiple columns single value search

I've used the following method to search for one single value in one single column.
/**
* #param array $searchArray
* #return array
*/
private static function returnPetSearchResults(array $searchArray): array
{
global $wpdb;
$qry = "SELECT ID
FROM {$wpdb->pets}
WHERE softDelete = 0
AND isAdopted = 0";
$parameters = [];
if ($searchArray['status'] !== '') {
$qry .= " AND status = %d";
$parameters[] = $searchArray['status'];
}
if ($searchArray['type']) {
$qry .= " AND type = %d";
$parameters[] = $searchArray['type'];
}
if ($searchArray['size']) {
$qry .= " AND size = %d";
$parameters[] = $searchArray['size'];
}
if ($searchArray['keyword']) {
$qry .= " AND name LIKE %s";
$parameters[] = '%'.$searchArray['keyword'].'%';
}
if ($searchArray['startDate']) {
$date = date('Y-m-d', strtotime($searchArray['startDate']));
$qry .= " AND dateEntered > %s";
$parameters[] = $date;
}
if ($searchArray['quarantineStatus'] != '') {
$qry .= " AND quarantineStatus = %d";
$parameters[] = $searchArray['quarantineStatus'];
}
if ($searchArray['kennel'] != '') {
$qry .= " AND kennel = %s";
$parameters[] = $searchArray['kennel'];
}
if ($searchArray['domain']) {
$qry .= " AND domain = %s";
$parameters[] = $searchArray['domain'];
}
$qry .= " ORDER BY ID DESC";
$sql = $wpdb->prepare($qry, $parameters);
return $wpdb->get_results($sql,OBJECT);
}
Now I want to extend to search one single value across multiple columns. I've searched online and you can see the few commented out examples I've tried.
/**
* #param array $searchArray
* #return array
*/
private static function returnPetSearchResults(array $searchArray): array
{
global $wpdb;
$qry = "SELECT ID
FROM {$wpdb->pets}
WHERE softDelete = 0
AND isAdopted = 0";
$parameters = [];
if ($searchArray['status'] !== '') {
$qry .= " AND status = %d";
$parameters[] = $searchArray['status'];
}
if ($searchArray['type']) {
$qry .= " AND type = %d";
$parameters[] = $searchArray['type'];
}
if ($searchArray['size']) {
$qry .= " AND size = %d";
$parameters[] = $searchArray['size'];
}
if ($searchArray['keyword']) {
$qry .= " AND name LIKE %s";
$parameters[] = '%'.$searchArray['keyword'].'%';
}
// if ($searchArray['keyword']) {
// $qry .= " WHERE name LIKE %s AND previousOwner LIKE %s";
// $parameters[] = '%'.$searchArray['keyword'].'%';
// }
// if ($searchArray['keyword']) {
// $qry .= " WHERE name = %s OR previousOwner = %s";
// $parameters[] = '%'.$searchArray['keyword'].'%';
// }
if ($searchArray['startDate']) {
$date = date('Y-m-d', strtotime($searchArray['startDate']));
$qry .= " AND dateEntered > %s";
$parameters[] = $date;
}
if ($searchArray['quarantineStatus'] != '') {
$qry .= " AND quarantineStatus = %d";
$parameters[] = $searchArray['quarantineStatus'];
}
if ($searchArray['kennel'] != '') {
$qry .= " AND kennel = %s";
$parameters[] = $searchArray['kennel'];
}
if ($searchArray['domain']) {
$qry .= " AND domain = %s";
$parameters[] = $searchArray['domain'];
}
$qry .= " ORDER BY ID DESC";
$sql = $wpdb->prepare($qry, $parameters);
return $wpdb->get_results($sql,OBJECT);
}
What am I missing to effectively search one single string value across multiple columns?
You would
- bind the parameters values
- escape the variable
- pass in logic to search any text in the string
- update your query to use LIKE instead of =
...
if ($searchArray['keyword']) {
$qry .= " AND
(name LIKE %s
OR previousOwner LIKE %s
OR intakeNotes LIKE %s
OR previousOwnerStreetAddress LIKE %s
OR previousOwnerCity LIKE %s
OR previousOwnerPhone LIKE %s
OR previousOwnerEmail LIKE %s
OR traits LIKE %s
OR dogBreed LIKE %s
OR catBreed LIKE %s)";
$parameters[] = '%'.$wpdb->esc_like($searchArray['keyword']).'%';
$parameters[] = '%'.$wpdb->esc_like($searchArray['keyword']).'%';
$parameters[] = '%'.$wpdb->esc_like($searchArray['keyword']).'%';
$parameters[] = '%'.$wpdb->esc_like($searchArray['keyword']).'%';
$parameters[] = '%'.$wpdb->esc_like($searchArray['keyword']).'%';
$parameters[] = '%'.$wpdb->esc_like($searchArray['keyword']).'%';
$parameters[] = '%'.$wpdb->esc_like($searchArray['keyword']).'%';
$parameters[] = '%'.$wpdb->esc_like($searchArray['keyword']).'%';
$parameters[] = '%'.$wpdb->esc_like($searchArray['keyword']).'%';
$parameters[] = '%'.$wpdb->esc_like($searchArray['keyword']).'%';
}
...

filter data pdo

What I am trying to do is similar to this. Search Filtering with PHP/MySQL
<?php
require 'con.php';
$minage = $_POST['data'][0];
$maxage = $_POST['data'][1];
$gender = $_POST['data'][2];
$religion = $_POST['data'][3];
$query = "SELECT CONCAT(firstname, ' ', middlename, ' ', lastname, ' ', extension_name) as fullname, TIMESTAMPDIFF(YEAR, birthday ,NOW()) as age FROM mytable";
$filter = array();
if($gender != -1){
$gender = substr($gender, 1, -1);
$filter[] = "gender = :gender";
}
if($religion != -1){
$filter[] = "religion = :religion";
}
if(count($filter) > 0){
$query .= " WHERE " . implode(' AND ', $filter);
$sql = $connection->prepare($query);
-> $sql->bindParam(':gender', $gender, PDO::PARAM_STR);
-> $sql->bindParam(':religion', $religion, PDO::PARAM_STR);
$sql->execute();
$res = $sql->fetchAll();
}else{
$sql = $connection->prepare($query);
$sql->execute();
$res = $sql->fetchAll();
}
?>
<?php foreach($res as $row): ?>
<div><?php echo $row['fullname'];?></div>
<?php endforeach; ?>
When I select a gender and religion on my dropdown, the result is fine.
But when I select only one, let's say gender, I received an error:
number of bound variables does not match number of tokens
I'm a bit confused where to place $sql->bindParam(...);. I guess this is the cause of my error? Or if there's more 'error' or if there's anything that's not right, please correct me. Thank you in advance.
Just add value right along with placeholder and then send them right to execute
if($gender != -1){
$filter[] = "gender = ?";
$values[] = $gender;
}
if($religion != -1){
$filter[] = "religion = ?";
$values[] = $religion;
}
$query .= " WHERE 1 AND " . implode(' AND ', $filter);
$stmt = $connection->prepare($query);
$stmt->execute($values);
Bind shoud be conditional also:
if($gender != -1){
$filter[] = "gender = :gender";
}
if($religion != -1){
$filter[] = "religion = :religion";
}
if(count($filter) > 0){
$gender = substr($gender, 1, -1);
$query .= " WHERE " . implode(' AND ', $filter);
$sql = $connection->prepare($query);
if($gender != -1){
$sql->bindParam(':gender', $gender, PDO::PARAM_STR);
}
if($religion != -1){
$sql->bindParam(':religion', $religion, PDO::PARAM_STR);
}
$sql->execute();
$res = $sql->fetchAll();
}else{
thats a very badly organized code, try to make it more readable

Multiple conditions queries with PDO

I asked this question in http://codereview.stackexchange.com and they wanted me to post it here. I couldn't get this code to work at all. I switched from regular mysql to pdo which is more safer. Could someone tell me what I'm missing here. I've been struggling with it for couple of day, and I could find exact answer when I first searched this site.
$input = $_POST['input'];
$categories = $_POST['category'];
$state = $_POST['state'];
$zipcode = $_POST['zipcode'];
$qq = $db->prepare(" SELECT * FROM classified ")or die(print_r($qq->errorInfo(), true));
/*** execute the prepared statement ***/
$qq->execute();
/*** echo number of columns ***/
$rows = $qq->fetch(PDO::FETCH_NUM);
if ($rows>0){
$query = (" SELECT * FROM classified ");
$cond = array();
$params = array();
if (!empty($input)) {
$cond[] = "title = ?";
$params[] = $input;
}
if (!empty($categories)) {
$cond[] = "id_cat = ?";
$params[] = $categories;
}
if (!empty($state)) {
$cond[] = "id_state = ?";
$params[] = $state;
}
if (!empty($zipcode)) {
$cond[] = "zipcode = ?";
$params[] = $zipcode;
}
if (count($cond)) {
$query .= ' WHERE ' . implode(' AND ', $cond)or
die(print_r($query->errorInfo(),true));
}
$stmt = $db->prepare($query);
$stmt->execute($params);
$ro = $stmt->fetch(PDO::FETCH_NUM);
}
if ($ro > 0) {
foreach ($stmt->fetchAll(PDO::FETCH_ASSOC) as $row)
{
echo $row['title'];
echo $row['categories'];
echo $row['state'];
echo $row['zipcode'];
}
}
I think it's a good idea to post an answer here rather than posting a link. I'm sure it will be useful for some people.
$input = $_POST['input'];
$categories = $_POST['category'];
$state = $_POST['state'];
$zipcode = $_POST['zipcode'];
$qq = $db->prepare(" SELECT * FROM classified ")or die(print_r($qq->errorInfo(),
true));
/*** execute the prepared statement ***/
$qq->execute();
/*** echo number of columns ***/
$rows = $qq->fetch(PDO::FETCH_NUM);
if ($rows>0){
$query = " SELECT * FROM classified where confirm='0' ";
if(!empty( $_POST['input'])) {
$query .= "AND title LIKE '%".$input."%' ";
}
if (!empty($_POST['category']) )
{
$query .= "AND id_cat = ".$categories." ";
}
if (!empty($_POST['state']) )
{
$query .= "AND id_state = ".$state." ";
}
if(!empty($_POST['zipcode'])) {
$query .= "AND zipcode = ".$zipcode." ";
}
$query .= "ORDER BY date ";
}
$stmt = $db->prepare($query);
$stmt->execute($params);
$result = $stmt->fetchAll();
// $ro = $stmt->fetch(PDO::FETCH_NUM);
// it didn't work when I tried to count rows
if ($result > 0) {
foreach ($result as $row)
{
echo $row['title'];
echo $row['categories'];
echo $row['state'];
echo $row['zipcode'];
}
}else{
echo " No data available";
}

two methods in a class so close in what they do

I have this class that has these two methods that are so closely related to the each other. I do not want to pass the flags so I kept them separate. I was wondering if there is a way to rewrite it so that I do not have to repeat so closely!
class Test extends Controller
{
public static function nonFormattedData($param)
{
$arr = array();
if (is_array($param)) {
$i = 0;
$sql = "
select *
from table1
where
";
if (isset($param['startDate'])) {
$sql .= " date_created between ? AND ?";
$arr[] = $param['startDate'];
$arr[] = $param['endDate'];
$i++;
}
if (isset($param['amount']) && !empty($param['amount'])) {
if ($i > 0) $sql .= " AND ";
$sql .= " balance= ?";
$arr[] = $param['amount'];
$i++;
}
if (isset($param) && !empty($param['amount'])) {
if ($i > 0) $sql .= " AND ";
$sql .= " balance= ?";
$arr[] = $param['amount'];
$i++;
}
if (isset($param['createdBy']) && !empty($param['createdBy'])) {
if ($i > 0) $sql .= " AND ";
$sql .= " column2 like '%Created By: " . $param['createdBy'] . "%'";
}
$sql .= ' group by id.table1 ';
$rs = Query::RunQuery($sql, $arr);
foreach ($rs as $row) {
$records = new Account();
$results[] = $records;
}
return $results;
}
}
public static function formattedData($serArray, $orderBy = "giftcardaccount_id desc", $offset = 0, $limit = 10)
{
$arr = array();
if (is_array($param)) {
$i = 0;
$sql = "
select *
from table1
where
";
if (isset($param['startDate'])) {
$sql .= " date_created between ? AND ?";
$arr[] = $param['startDate'];
$arr[] = $param['endDate'];
$i++;
}
if (isset($param['amount']) && !empty($param['amount'])) {
if ($i > 0) $sql .= " AND ";
$sql .= " balance= ?";
$arr[] = $param['amount'];
$i++;
}
if (isset($param) && !empty($param['amount'])) {
if ($i > 0) $sql .= " AND ";
$sql .= " balance= ?";
$arr[] = $param['amount'];
$i++;
}
if (isset($param['createdBy']) && !empty($param['createdBy'])) {
if ($i > 0) $sql .= " AND ";
$sql .= " column2 like '%Created By: " . $param['createdBy'] . "%'";
}
$sql .= ' group by id.table1 ';
$rs = Query::RunQuery($sql, $arr);
return array("data" => $rs);
}
}
}
Why not have one method, but with an optional formatting options object/array?
public static function getData($params, $formatting = null) {
// continue as normal, adding formatting if it's there
}

Categories