filter data pdo - php

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

Related

PHP CRUD operations with search, and operator

I am using below function ( i got this from internet) to fetch data from DB and its working fine. If i use where and search condition is not working properly or i have missed some thing. Can any one help me to fix this issue.
public function getRows($table,$conditions = array()){
$sql = 'SELECT ';
$sql .= array_key_exists("select",$conditions)?$conditions['select']:'*';
$sql .= ' FROM '.$table;
if(array_key_exists("where",$conditions)){
$sql .= ' WHERE ';
$i = 0;
foreach($conditions['where'] as $key => $value){
$pre = ($i > 0)?' AND ':'';
echo $sql .= $pre.$key." = '".$value."'";
$i++;
}
}
if(array_key_exists("search",$conditions)){
$sql .= (strpos($sql, 'WHERE') !== false)?'':' WHERE ';
$i = 0;
foreach($conditions['search'] as $key => $value){
$pre = ($i > 0)?' OR ':'';
$sql .= $pre.$key." = '".$value."'";
$i++;
}
}
if(array_key_exists("order_by",$conditions)){
$sql .= ' ORDER BY '.$conditions['order_by'];
}
if(array_key_exists("start",$conditions) && array_key_exists("limit",$conditions)){
$sql .= ' LIMIT '.$conditions['start'].','.$conditions['limit'];
}elseif(!array_key_exists("start",$conditions) && array_key_exists("limit",$conditions)){
echo $sql .= ' LIMIT '.$conditions['limit'];
}
$query = $this->conn->prepare($sql);
$query->execute();
if(array_key_exists("return_type",$conditions) && $conditions['return_type'] != 'all'){
switch($conditions['return_type']){
case 'count':
$data = $query->rowCount();
break;
case 'single':
$data = $query->fetch(PDO::FETCH_ASSOC);
break;
default:
$data = '';
}
}else{
if($query->rowCount() > 0){
$data = $query->fetchAll();
}
}
return !empty($data)?$data:false;
}
Function used with where and Search condition
if(!empty($_POST['customer_number'])) {
$ajaxData = $auth_user->getRows(
'tablename',
array('where' => array('fieldName'=>$doc)),
array('search'=> array('fieldname1'=>$_POST['customer_number'], 'fieldname2'=>$_POST['customer_number']))
);
}
Result of the above code is
SELECT * FROM tablename WHERE cust_consum_type = '1'
Expected Result is.
select * from tablename where fieldName='somevalue' and fieldname1='somevalue' OR fieldname2='somevalue'
Help me to fix this issue.
This function is so wrong on so many levels, being critically insecure in the first place.
Instead, use vanilla PDO. Make your function this way
public function getRows($sql,$input = array()){
$stmt = $this->conn->prepare($sql);
$stmt->execute($input);
return $stmt;
}
Then just write your query right away with placeholders, pass the data in pparameters and have the result:
$sql = "select * from tablename where fieldName=:fieldName
and (fieldname1=:fieldName1 OR fieldname2=:fieldName2)";
$input = ['fieldName'=>$doc,
'fieldname1'=>$_POST['customer_number'],
'fieldname2'=>$_POST['customer_number']];
$data = $db->getRows($sql, $input)->fetchAll();
it will be safe, clean, always working, safe, flexible, safe from SQL injections and syntax errors.

Dynamic mysql query in prepared

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;

Why am I receiving only the first value for each element of the array?

I am not able to figure out why all of my results are repetitions of the first values it returns.
This code returns the same ID and formatted date repeated over and over again; however, I was expecting it to read a value and then transform that value for each entry in the DB. Here is my code:
<?php
include('../includes/conn.inc.php');
$stmt = $mysql->prepare("SELECT id, endDate FROM TABLE ORDER BY id");
$stmt->execute();
$stmt->bind_result($id, $endDate);
while($row = $stmt->fetch()) {
$dataRow[] = array('id'=>$id,'endDate'=> $endDate);
};
foreach($dataRow as $i) {
$newEndDate = date('Y-m-d',strtotime($endDate));
$sql = 'UPDATE TABLE SET startDate = ? WHERE id= ? ';
$stmt = $mysql->stmt_init();
if ($stmt->prepare($sql)) {
$stmt->bind_param('si',$newEndDate, $id);
$OK = $stmt->execute();}
if ($OK) {
echo $id . " " . $newEndDate . "done <br/>";
} else {
echo $stmt->error;
}
$stmt->close();
};
In your foreach you are always using the last values that were set from the last $stmt->fetch()
Try:
foreach($dataRow as $i) {
$newEndDate = date('Y-m-d',strtotime($i['endDate']));
$id = $i['id'];
$sql = 'UPDATE TABLE SET startDate = ? WHERE id= ? ';
$stmt = $mysql->stmt_init();
if ($stmt->prepare($sql)) {
$stmt->bind_param('si',$newEndDate, $id);
$OK = $stmt->execute();
}
if ($OK) {
echo $id . " " . $newEndDate . "done <br/>";
} else {
echo $stmt->error;
}
$stmt->close();
};
use get_result();
$dataRow = array()
$stmt = $mysql->prepare("SELECT id, endDate FROM TABLE ORDER BY id");
$stmt->execute();
$result = $stmt->get_result();
while($row = $result->fetch_array()) {
$dataRow[$row['id']] = $row['endDate'];
}
and you don't populate your $endDate in the second loop
foreach($dataRow as $i => $endDate){
$newEndDate = date('Y-m-d',strtotime($endDate));
... // rest of your code

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

Improving my SELECTs that use PDO and adding an UPDATE statement

I'm using the following code to select data from a MySQL table. Can someone tell me how to improve this as it seems a bit messy?
Also, I need to run an UPDATE statement to increment the value in the "views" column each time a customer is queried from the database. Each customer row in the database has a column named "views". For example, say ABC Corp has 100 views. If I search for ABC Corp and the database returns the record, the "views" column for this record should be updated to 101. What is the best way to do this?
if ($search && ($group && $group !== "*")) {
$sql = "SELECT * FROM customers WHERE description LIKE :description AND groupId LIKE :groupId";
$result = $conn->prepare($sql);
$result->bindValue(":description", "%" . $search . "%", PDO::PARAM_STR);
$result->bindValue(":groupId", $groupId, PDO::PARAM_INT);
} else if ($search) {
$sql = "SELECT * FROM customers WHERE description LIKE :description";
$result = $conn->prepare($sql);
$result->bindValue(":description", "%" . $search . "%", PDO::PARAM_STR);
} else if ($group !== "*") {
$sql = "SELECT * FROM customers WHERE groupId LIKE :groupId";
$result = $conn->prepare($sql);
$result->bindValue(":groupId", $groupId, PDO::PARAM_INT);
} else {
$sql = "SELECT * FROM customers";
$result = $conn->prepare($sql);
}
How about something like this,
$sql = "SELECT * FROM customers ";
$and = $grp = FALSE;
if($search || ($group && $group !== "*") {
$sql .= " WHERE ";
if ($search) {
$sql .= " description LIKE :description ";
$and = TRUE;
}
if ($group && $group !== "*") {
if( $and === TRUE )
$sql .= " AND ";
$sql .= " groupId LIKE :groupId ";
$grp = TRUE;
}
}
$result = $conn->prepare($sql);
if( $and === TRUE)
$result->bindValue(":description", "%" . $search . "%", PDO::PARAM_STR);
if( $grp === TRUE)
$result->bindValue(":groupId", $groupId, PDO::PARAM_INT);
For the UPDATE statement,
//say $cust_name is the requested customer to be searched
$sql = "SELECT views from customers where customer_name = '" $cust_name."'";
$res = $conn->query($sql);
$views = $res->fetchColumn() + 1;
//sets 'views' to num_of_customers/rows returned.
$sql = "UPDATE customers SET VIEWS = " .$views." WHERE customer_name = '" $cust_name."'";
$res = $conn->query($sql);

Categories