pdo and like query - php

I have a query and it looks like:
if (strlen($search->q)) {
$where[] = ' AND (`name` LIKE :q)';
$arr['q'] = "%" . $search->q . "%";
}
$sql = 'SELECT
*,
FROM
`shop_products`
WHERE
1=1
'.implode('', $where);
Not I'm trying to get products from DB:
$result->products = $db->query($sql, $arr, $search->limitstart, $search->limit)->fetchAll();
My query function:
public function query($sql, $params=array(), $offset = null, $limit = null){
if (!is_null($offset) && !is_null($limit)) {
$sql .= ' LIMIT :limit OFFSET :offset';
$params['limit'] = (int)$limit;
$params['offset'] = (int)$offset;
}
$stmt = $this->database->prepare($sql);
if (!empty($params)) {
foreach($params as $key => $value) {
if(is_int($value)) {
$param = PDO::PARAM_INT;
} elseif(is_bool($value)) {
$param = PDO::PARAM_BOOL;
} elseif(is_null($value)) {
$param = PDO::PARAM_NULL;
} elseif(is_string($value)) {
$param = PDO::PARAM_STR;
} else {
$param = false;
}
if($param) $stmt->bindValue(":$key", $value, $param);
}
}
$stmt->execute();
return $stmt;
}
My problem that LIKE instruction does not work. How can I solve this problem and fix my code?

Related

Can UNICODE characters be set as parameters in php?

The column names of my table are in UNICODE characters. So, can those characters be set as parameters?
This is the SQL:
INSERT INTO सामान्य_ग्यान
SET मिति = :मिति, शीर्षक = :शीर्षक, विकल्प_क = :विकल्प_क, विकल्प_ख = :विकल्प_ख, विकल्प_ग = :विकल्प_ग,
विकल्प_घ = :विकल्प_घ, सही_जवाफ = :सही_जवाफ
And if I run this query then it throws the following error.
Insert Query: SQLSTATE[42000]: Syntax error or access violation: 1064 You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near ':मिति, शीर्षक = :शीर्षक, विकल्प_क ' at line 1
Here is my insert code:
final protected function insert($data, $is_die = false){
try {
$this->sql = "INSERT INTO ";
if (!isset($this->table) || empty($this->table)) {
throw new Exception("Table not set");
}
$this->sql .= $this->table;
$this->sql .= " SET ";
if (isset($data) && !empty($data)) {
if (is_array($data)) {
$temp = array();
foreach ($data as $column_name => $value) {
$str = $column_name." = :".$column_name;
$temp[] = $str;
}
$this->sql .= implode(', ', $temp);
} else {
$this->sql .= $data;
}
}
$this->stmt = $this->conn->prepare($this->sql);
if (isset($data) && !empty($data) && is_array($data)) {
foreach ($data as $column_name => $value) {
if (is_int($value)) {
$param = PDO::PARAM_INT;
} elseif (is_bool($value)) {
$param = PDO::PARAM_BOOL;
} elseif (is_null($value)) {
$value = null;
$param = PDO::PARAM_INT;
} else {
$param = PDO::PARAM_STR;
}
if ($param) {
$this->stmt->bindValue(":".$column_name, $value, $param);
}
}
}
if ($is_die) {
debugger($this->sql, true);
echo $this->sql;
}
/*error*/
$this->stmt->execute();
/*error*/
return $this->conn->lastInsertId();
} catch (PDOException $e) {
error_log(
date('Y-m-d h:i:s A').", Insert Query: ".$e->getMessage()."\r\n"
, 3, ERROR_PATH.'error.log');
return false;
} catch (Exception $e) {
error_log(
date('Y-m-d h:i:s A').", General: ".$e->getMessage()."\r\n"
, 3, ERROR_PATH.'/error.log');
return false;
}
}

Sending an array of parameters to bind_param

I have the parameters to send to a prepared statement in an array, I am using call_user_func_array and using it as such call_user_func_array(array($stmt, "bind_param"), array_merge(array($types), $params_fixed)), where $types contains the types and $params_fixed contains the parameters.
I ran it and got the error Warning: Parameter 2 to mysqli_stmt::bind_param() expected to be a reference, value given in ..., I searched for this error and an answer was to send the parameters by reference so I added an ampersand before the $params_fixed parameter however now I get the error Fatal error: Call-time pass-by-reference has been removed in ....
How can I resolve this issue? What am I missing here?
NOTE: Before learning I had to use call_user_func_array, I was using it as such $stmt->bind_param($types, ...$params_fixed)
NOTE 2: below is the code for filling the array to send
$params_fixed = array();
$types = "";
if($param_count > 0) {
foreach($params as $param) {
switch(gettype($param)) {
case "boolean":
$types = $types . "i";
$params_fixed[] = $param ? 1 : 0;
break;
case "integer":
$types = $types . "i";
$params_fixed[] = &$param;
break;
case "double":
$types = $types . "d";
$params_fixed[] = &$param;
break;
case "string":
$types = $types . "s";
$params_fixed[] = &$param;
break;
default:
$types = $types . "s";
$params_fixed[] = null;
break;
}
}
}
NOTE 3: below is the code in question
public function query($sql, ...$params) {
$param_num_sql = substr_count($sql, "?");
$param_count = count($params);
if($param_num_sql != $param_count) {
$this->error = 'parameters don\'t match';
return null;
}
$params_fixed = array();
$types = "";
if($param_count > 0) {
foreach($params as $param) {
$types = $types . "s";
$params_fixed[] = &$param;
// switch(gettype($param)) {
// case "boolean":
// $types = $types . "i";
// $params_fixed[] = $param ? 1 : 0;
// break;
// case "integer":
// $types = $types . "i";
// $params_fixed[] = $param;
// break;
// case "double":
// $types = $types . "d";
// $params_fixed[] = $param;
// break;
// case "string":
// $types = $types . "s";
// $params_fixed[] = $param;
// break;
// default:
// $types = $types . "s";
// $params_fixed[] = null;
// break;
// }
}
}
if($param_num_sql == 0) {
$result = $this->conn->query($sql);
} else {
$stmt = $this->conn->prepare($sql);
//call_user_func_array(array($stmt, "bind_param"), array_merge(array($types), $params_fixed));
//if(!$stmt->bind_param($types, ...$params_fixed)) {
echo "<br/>types: $types<br/>";
echo '<br/>';
print_r($params_fixed);
echo '<br/>';
if(!call_user_func_array(array($stmt, "bind_param"), array_merge(array($types), $params_fixed))) {
// an error occurred
}
$stmt->execute();
$result = $stmt->get_result();
$stmt->close();
}
if($result != null && $result->num_rows > 0)
return $result->fetch_all();
else
return null;
}
and below is the code calling this method
$dbcon->query($query, $fname, $mname, $lname, $dob, $mobile, $home, $email, $area, $city, $street, $bldg, $floor, $car_capacity, $status, $prefer_act, $volunteer_days, $backup_days);
try like this
$mysqli = new mysqli('localhost', 'root','','mydb');
$stmt=$mysqli->prepare("select * from blog where id=? and date=?");
$title='1';
$text='2016-04-07';
call_user_func_array(array($stmt, "bind_param"),array_merge(array('ss'),array(&$title,&$text)));
$stmt->execute();
$result = $stmt->get_result();
print_r($result->fetch_array());
echo $stmt->error;
ok if you have parameters coming from the array
$mysqli = new mysqli('localhost', 'root','','jobspace');
$stmt=$mysqli->prepare("select * from listings where listing_type_sid=? and user_sid=?");
$title='6';
$text='8';
$arr=array($title,$text);
foreach($arr as &$ar){
$new[]=&$ar;
}
$types = implode(array_fill(0,count($arr),'s'));
call_user_func_array(array($stmt, "bind_param"),array_merge(array($types),$new));
$stmt->execute();
$result = $stmt->get_result();
print_r($result->fetch_array());
echo $stmt->error;

when i run my program it keeps throwing these errors

Warning: Missing argument 1 for MysqlDB::__construct(), called in C:\xampp\htdocs\ripplezsolution\index.php on line 9 and defined in C:\xampp\htdocs\ripplezsolution\phpinclude\include\MySqlDb.php on line 10
Warning: Missing argument 2 for MysqlDB::__construct(), called in C:\xampp\htdocs\ripplezsolution\index.php on line 9 and defined in C:\xampp\htdocs\ripplezsolution\phpinclude\include\MySqlDb.php on line 10
Warning: Missing argument 3 for MysqlDB::__construct(), called in C:\xampp\htdocs\ripplezsolution\index.php on line 9 and defined in C:\xampp\htdocs\ripplezsolution\phpinclude\include\MySqlDb.php on line 10
Warning: Missing argument 4 for MysqlDB::__construct(), called in C:\xampp\htdocs\ripplezsolution\index.php on line 9 and defined in C:\xampp\htdocs\ripplezsolution\phpinclude\include\MySqlDb.php on line 10
Notice: Undefined variable: host in C:\xampp\htdocs\ripplezsolution\phpinclude\include\MySqlDb.php on line 11
Notice: Undefined variable: username in C:\xampp\htdocs\ripplezsolution\phpinclude\include\MySqlDb.php on line 11
Notice: Undefined variable: password in C:\xampp\htdocs\ripplezsolution\phpinclude\include\MySqlDb.php on line 11
Notice: Undefined variable: db in C:\xampp\htdocs\ripplezsolution\phpinclude\include\MySqlDb.php on line 11
This is my MysqlDB.php code
<?php
class MysqlDB {
protected $_mysql;
protected $_where = array();
protected $_query;
protected $_paramTypeList;
public function __construct ($host, $username, $password, $db) {
$this->_mysql = new mysqli($host, $username, $password, $db)
or die('There was a problem connecting to the database');
}
public function query($query)
{
$this->_query = filter_var($query, FILTER_SANITIZE_STRING);
$stmt = $this->_prepareQuery();
$stmt->execute();
$results = $this->_dynamicBindResults($stmt);
return $results;
}
/**
* A convenient SELECT * function.
*
* #param string $tableName The name of the database table to work with.
* #param int $numRows The number of rows total to return.
* #return array Contains the returned rows from the select query.
*/
public function get($tableName, $numRows = NULL)
{
$this->_query = "SELECT * FROM $tableName";
$stmt = $this->_buildQuery($numRows);
$stmt->execute();
$results = $this->_dynamicBindResults($stmt);
return $results;
}
/**
*
* #param <string $tableName The name of the table.
* #param array $insertData Data containing information for inserting into the DB.
* #return boolean Boolean indicating whether the insert query was completed succesfully.
*/
public function insert($tableName, $insertData)
{
$this->_query = "INSERT into $tableName";
$stmt = $this->_buildQuery(NULL, $insertData);
$stmt->execute();
if ($stmt->affected_rows)
return true;
}
public function update($tableName, $tableData)
{
$this->_query = "UPDATE $tableName SET ";
$stmt = $this->_buildQuery(NULL, $tableData);
$stmt->execute();
if ($stmt->affected_rows)
return true;
}
public function delete($tableName) {
$this->_query = "DELETE FROM $tableName";
$stmt = $this->_buildQuery();
$stmt->execute();
if ($stmt->affected_rows)
return true;
}
public function where($whereProp, $whereValue)
{
$this->_where[$whereProp] = $whereValue;
}
protected function _determineType($item)
{
switch (gettype($item)) {
case 'string':
return 's';
break;
case 'integer':
return 'i';
break;
case 'blob':
return 'b';
break;
case 'double':
return 'd';
break;
}
}
protected function _buildQuery($numRows = NULL, $tableData = false)
{
$hasTableData = null;
if (gettype($tableData) === 'array') {
$hasTableData = true;
}
// Did the user call the "where" method?
if (!empty($this->_where)) {
$keys = array_keys($this->_where);
$where_prop = $keys[0];
$where_value = $this->_where[$where_prop];
// if update data was passed, filter through
// and create the SQL query, accordingly.
if ($hasTableData) {
$i = 1;
$pos = strpos($this->_query, 'UPDATE');
if ( $pos !== false) {
foreach ($tableData as $prop => $value) {
// determines what data type the item is, for binding purposes.
$this->_paramTypeList .= $this->_determineType($value);
// prepares the reset of the SQL query.
if ($i === count($tableData)) {
$this->_query .= $prop . " = ? WHERE " . $where_prop . "= " . $where_value;
} else {
$this->_query .= $prop . ' = ?, ';
}
$i++;
}
}
} else {
$this->_paramTypeList = $this->_determineType($where_value);
$this->_query .= " WHERE " . $where_prop . "= ?";
}
}
if ($hasTableData) {
$pos = strpos($this->_query, 'INSERT');
if ($pos !== false) {
$keys = array_keys($tableData);
$values = array_values($tableData);
$num = count($keys);
foreach ($values as $key => $val) {
$values[$key] = "'{$val}'";
$this->_paramTypeList .= $this->_determineType($val);
}
$this->_query .= '(' . implode($keys, ', ') . ')';
$this->_query .= ' VALUES(';
while ($num !== 0) {
($num !== 1) ? $this->_query .= '?, ' : $this->_query .= '?)';
$num--;
}
}
}
if (isset($numRows)) {
$this->_query .= " LIMIT " . (int) $numRows;
}
$stmt = $this->_prepareQuery();
if ($hasTableData) {
$args = array();
$args[] = $this->_paramTypeList;
foreach ($tableData as $prop => $val) {
$args[] = &$tableData[$prop];
}
call_user_func_array(array($stmt, 'bind_param'), $args);
} else {
if ($this->_where)
$stmt->bind_param($this->_paramTypeList, $where_value);
}
return $stmt;
}
protected function _dynamicBindResults($stmt)
{
$parameters = array();
$results = array();
$meta = $stmt->result_metadata();
while ($field = $meta->fetch_field()) {
$parameters[] = &$row[$field->name];
}
call_user_func_array(array($stmt, 'bind_result'), $parameters);
while ($stmt->fetch()) {
$x = array();
foreach ($row as $key => $val) {
$x[$key] = $val;
}
$results[] = $x;
}
return $results;
}
protected function _prepareQuery()
{
if (!$stmt = $this->_mysql->prepare($this->_query)) {
trigger_error("Problem preparing query", E_USER_ERROR);
}
return $stmt;
}
public function __destruct()
{
$this->_mysql->close();
}
}
?>
and i'm calling a function insert() through index.php
<?php
ob_start();
session_start();
require_once("phpinclude/include/membersite_config.php");
require_once("phpinclude/include/MySqlDB.php");
$DB = new MysqlDB('172.90.13.97','king','mi*****hhh','kxxxx_database');
if (isset($_GET['action'])){$action = htmlentities($_GET['action']);}
else{$action = NULL;}
$mysqldb = new MysqlDB();
?>
<?php if($action=='add_cart'){?>
<?php $data=array($arrival, $departure, $result, $roomID, $category_price); $table='tb_cart';?>
<?php $this->mysqldb->insert($table, $data); ?>
<?php }?>
Problem is in this line
$mysqldb = new MysqlDB();
The constructor requries arguments which are not passed. You need to pass $host, $username, $password, $db to constructor.
Your code acutally makes no sense. You could use $DB instead of creating new object. You also use $this->mysqldb in no object context. There are plenty of errors in your code.
To fix:
Remove this line $mysqldb = new MysqlDB();
Change <?php $this->mysqldb->insert($table, $data); ?> to $DB->insert($table, $data);
Script should +- look like:
<?php
ob_start();
session_start();
require_once("phpinclude/include/membersite_config.php");
require_once("phpinclude/include/MySqlDB.php");
$DB = new MysqlDB('172.90.13.97','king','mi*****hhh','kxxxx_database');
$action = !empty($_GET['action']) ? htmlentities($_GET['action']) : null;
if ($action == 'add_cart') {
$data = array(
'arrival' => $arrival,
'departure' => $departure,
'result' => $result,
'roomID' => $roomID,
'category_price' => $category_price
);
$DB->insert('tb_cart', $data);
}

Database class, OOP - connect to mysql

This is database class:
DB.php
<?php
class DB {
public static $instance = null;
private $_pdo = null,
$_query = null,
$_error = false,
$_results = null,
$_count = 0;
private function __construct() {
try {
$this->_pdo = new PDO('mysql:host=' . Config::get('mysql/host') . ';dbname=' . Config::get('mysql/db'), Config::get('mysql/username'), Config::get('mysql/password'));
} catch(PDOExeption $e) {
die($e->getMessage());
}
}
public static function getInstance() {
// Already an instance of this? Return, if not, create.
if(!isset(self::$instance)) {
self::$instance = new DB();
}
return self::$instance;
}
public function query($sql, $params = array()) {
$this->_error = false;
if($this->_query = $this->_pdo->prepare($sql)) {
$x = 1;
if(count($params)) {
foreach($params as $param) {
$this->_query->bindValue($x, $param);
$x++;
}
}
if($this->_query->execute()) {
$this->_results = $this->_query->fetchAll(PDO::FETCH_OBJ);
$this->_count = $this->_query->rowCount();
} else {
$this->_error = true;
}
}
return $this;
}
public function get($table, $where) {
return $this->action('SELECT *', $table, $where);
}
public function delete($table, $where) {
return $this->action('DELETE', $table, $where);
}
public function action($action, $table, $where = array()) {
if(count($where) === 3) {
$operators = array('=', '>', '<', '>=', '<=');
$field = $where[0];
$operator = $where[1];
$value = $where[2];
if(in_array($operator, $operators)) {
$sql = "{$action} FROM {$table} WHERE {$field} {$operator} ?";
if(!$this->query($sql, array($value))->error()) {
return $this;
}
}
return false;
}
}
public function insert($table, $fields = array()) {
$keys = array_keys($fields);
$values = null;
$x = 1;
foreach($fields as $value) {
$values .= "?";
if($x < count($fields)) {
$values .= ', ';
}
$x++;
}
$sql = "INSERT INTO {$table} (`" . implode('`, `', $keys) . "`) VALUES ({$values})";
if(!$this->query($sql, $fields)->error()) {
return true;
}
return false;
}
public function update($table, $id, $fields = array()) {
$set = null;
$x = 1;
foreach($fields as $name => $value) {
$set .= "{$name} = ?";
if($x < count($fields)) {
$set .= ', ';
}
$x++;
}
$sql = "UPDATE users SET {$set} WHERE id = {$id}";
if(!$this->query($sql, $fields)->error()) {
return true;
}
return false;
}
public function results() {
// Return result object
return $this->_results;
}
public function first() {
return $this->_results[0];
}
public function count() {
// Return count
return $this->_count;
}
public function error() {
return $this->_error;
}
}
I was looking this database approach and it seems very practical and useful. I'm beginner at oop and still learning. The requestQuote would look something like this:
How do I bindParam in query like this?
requestQuote = DB::getInstance()->query(""); (form DB.class)
This is code I have right now:
$request = "";
if ($_POST) {
$request = $_POST["request"];
} else if (isset($_GET["request"])) {
$request = $_GET["request"];
}
$requestQuote="%" . $request . "%";
$sql = $conn -> prepare("SELECT * FROM users WHERE concat(name, ' ',lastname, ' ', user_id) LIKE :request limit " . (($page * 50)-50) . ",50");
$sql->bindParam(":request", $requestQuote);
$sql -> execute();
$results = $sql -> fetchAll(PDO::FETCH_OBJ);
When I put it like this, then pagination works. But I need search form... and that won't work...
$sql= DB::getInstance()->query(
"SELECT * FROM users
WHERE (category='admin')
LIMIT " . (($page* 5)-5) . ",5");
#Paul was close but you got one more issue:
Check this part of the class:
$x = 1;
if(count($params)) {
foreach($params as $param) {
$this->_query->bindValue($x, $param);
$x++;
}
}
It is not binding with named place holder, you need to change the code:
$limit = ($page * 50)-50;
$params = array('%lolcats%', $limit);
$query =
"SELECT * FROM users
WHERE concat(name, ' ',lastname, ' ', user_id)
LIKE ?
LIMIT ?,50";
$results = DB::getInstance()->query($query, $params);
or change the class code to bind by placeholder, something along the following lines:
#$params = array(':request' =>'%lolcats%', ':limit'=>$limit);
if(count($params)) {
foreach($params as $key=>$value) {
$this->_query->bindValue($key, $value);
}
}
Looking at this class, the second argument of query function is an optional array of parameters so use this to pass the parameters for your request:
$params = array(':request' => 'lolcats');
$limit = $page - 1 * 50;
$query = sprintf(
"SELECT * FROM users
WHERE concat(name, ' ',lastname, ' ', user_id)
LIKE :request
LIMIT %d,50",
$limt
);
$results = DB::getInstance()->query($query, $params);

Select and call_user_func_array issue

I've this function:
private function db_bind_array($stmt, &$row) {
$md = $stmt->result_metadata();
$param = array();
while($field = $md->fetch_field()) { $param[] = &$row[$field->name];}
return call_user_func_array(array($stmt, 'bind_result'), $param);
}
private function db_query($sql, $bind_param, $param) {
if($stmt = $this->conn->prepare($sql)) {
if(!$bindRet = call_user_func_array(array($stmt,'bind_param'),
array_merge(array($bind_param), $param))) $this->Terminate();
if(!$stmt->execute()) $this->Terminate();
$res = array();
if($this->db_bind_array($stmt, $res)) return array($stmt, $res);
}
}
protected function Select($recs, $table, $where, $bind_param, $param, $order_by = '', $sort = '', $limit = 1) {
if($order_by != '') $order_by = 'ORDER BY '.$order_by;
$sql = "SELECT $recs FROM $table WHERE $where $order_by $sort LIMIT $limit";
return $this->ExeSelect($sql, $bind_param, $param);
}
private function ExeSelect($sql, $bind_param, $param) {
if($res = $this->db_query($sql, $bind_param, array(&$param))) {
$stmt = $res[0]; $row = $res[1];
while($stmt->fetch()) {$this->row = $row; return $row;}
$stmt->close();
}
}
And I use it:
$row = $this->Select('id, name, title, 'Articles', where id >, 'i', 10, 'DESC', '', 10)
The problem is that it returns only one record instead of 10.
What's the problem?
Thanks
The problem is this line: while($stmt->fetch()) {$this->row = $row; return $row;}. You immediately return that result. Build an array before you return it.
private function ExeSelect($sql, $bind_param, $param) {
$ret = array();
if($res = $this->db_query($sql, $bind_param, array(&$param))) {
$stmt = $res[0]; $row = $res[1];
while($stmt->fetch()) {$ret[] = $row; }
$stmt->close();
}
return $ret;
}

Categories