Can UNICODE characters be set as parameters in php? - 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;
}
}

Related

sql and php - is there ant issue with this query or code

hi guys here is my update function it takes some parameters and eveluates them if they are integer or string after that process the values and throws for query sentence...
public function update ($table, $cols, $values, $addition) {
$db = $this->connect();
$i = 0;
$update = '';
if ((is_array($cols)) && (is_array($values))) {
foreach ($cols as $a) {
if (!is_int($values[$i])) {
$update = $a.'="'.$values[$i].'",';
} else {
$update = $a.'='.$values[$i].',';
}
$i++;
}
$update = substr($update, 0, -1);
} else {
if (!is_int($values)) {
$update = $cols.'="'.$values.'",';
} else {
$update = $cols.'='.$values.',';
}
}
echo "update ".$table." set ".$update." ".$addition."<br>";
try {
$sql = $db->prepare("update ".$table." set ".$update." ".$addition);
$sql->execute();
} catch (PDOException $e) {
print $e->getMessage();
}
$db = null;
}
and here are the parameters and the sql query
$this->db->update("brands", "car_count", $brandCarCount[0]+1, "where brand = '".$brand."'");
update brands set car_count=2, where brand = 'alfa_romeo'
i really do not understand what happens, i can not find the problem. it works for other inserting selecting or deleting functions.
i need help!
That is the relevant line which removes the trailing comma:
$update = rtrim($update,',');
and this is the full code:
public function update ($table, $cols, $values, $addition) {
$db = $this->connect();
$i = 0;
$update = '';
if ((is_array($cols)) && (is_array($values))) {
foreach ($cols as $a) {
if (!is_int($values[$i])) {
$update = $a.'="'.$values[$i].'",';
} else {
$update = $a.'='.$values[$i].',';
}
$i++;
}
} else {
if (!is_int($values)) {
$update = $cols.'="'.$values.'",';
} else {
$update = $cols.'='.$values.',';
}
}
$update = rtrim($update,',');
echo "update ".$table." set ".$update." ".$addition."<br>";
try {
$sql = $db->prepare("update ".$table." set ".$update." ".$addition);
$sql->execute();
} catch (PDOException $e) {
print $e->getMessage();
}
$db = null;
}

pdo and like query

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?

PDO Prepare for class DB

I have a class 'DB' of which i have taken from an online tutorial. It has some SELECT queries but not INSERT.
Its worked really well so far but i would like to develop it further for future use.
class DB {
private static $_instance = null;
private $_pdo,
$_query,
$_error = false,
$_errorMsg,
$_results,
$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(PDOException $e){
die($e->getMessage());
}
}
public static function getInstance() {
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 {
// return error & write to log
$this->_error = true;
//get Error message and save to log
$errormsg = $this->_query->errorInfo();
$message = date('l jS \of F Y h:i:s A') . "\n";
$message .= 'Invalid query: ' . $errormsg[2] . "\n";
$message .= 'Whole query: ' . $sql . "\n";
$message .= '------------------------------------------------------' . "\n";
$this->createLog($message);
$this->_errorMsg = $errormsg[2];
}
}
return $this;
}
public function action($action, $table, $where = array(), $and = array()) {
if(count($where) === 3){
$operators = array('=', '>', '<', '>=', '<=');
$field = $where[0];
$operator = $where[1];
$value = $where[2];
// Check if AND is set
$and = array_filter($and);
if ( !empty($and) && $and != '' ) {
$andOR = $and[0];
$andField = $and[1];
$andFieldOperator = $and[2];
$andValue = $and[3];
if(in_array($operator, $operators)) {
$sql = "{$action} FROM {$table} WHERE {$field} {$operator} ? {$andOR} `{$andField}` {$andFieldOperator} '{$andValue}'";
if( !$this->query($sql, array($value) )->error()) {
//print_r( $this->query($sql, array($value)));
return $this;
} else {
print_r('ERROR: Check error log - Click here');
}
}
} else {
if(in_array($operator, $operators)) {
$sql = "{$action} FROM {$table} WHERE {$field} {$operator} ?";
if( !$this->query($sql, array($value) )->error()) {
return $this;
} else {
print_r('ERROR: Check error log - Click here');
}
}
}
} else {
$sql = "{$action} FROM {$table}";
if( !$this->query($sql )->error()) {
return $this;
}
}
return false;
}
How can i add a function 'INSERT' for adding data to my database using PDO prepare?

Insert MySql data from array [duplicate]

This question already has an answer here:
Mysqli prepared statements build INSERT query dynamically from array
(1 answer)
Closed 6 months ago.
<?php
$files=array(name1,name2,name3,);
$conn = new mysqli($host, $user, $pass, $name);
if ($conn->connect_error) {
die("Connection failed: " . $conn->connect_error);
}
$sql = "INSERT INTO parmi_files (name)
VALUES ('$files')"; ///// -problem is here
if ($conn->query($sql) === TRUE) {
echo "New record created successfully";
} else {
echo "Error: " . $sql . "<br>" . $conn->error;
}
?>
I want to insert each value from array to MySql row, please solve it out.
Iterate through the items in the array and add them individually:
foreach ($arrayWithValues as $key=>$value) {
$sql = "INSERT INTO parmi_files (name) VALUES ('$value')";
mysqli_query($conn, $sql);
}
Something like this to insert multiple records at once:
$files = array('name1', 'name2', 'name3');
// ...
$filesMap = implode(',', array_map(function($value) {
return "('" . $conn->real_escape_string($value) . "')";
}, $files));
$sql = "INSERT INTO parmi_files (name) VALUES $filesMap";
You could use a PDO abstraction layer for this
I have made a class for this in the past
It uses: PDO, bound parameters, prepared statements
and it inserts everything in one sql query and the insert looks like this:
$db->insertRows('test_table', $default_row, $rows);
The full code
(which might seem a bit long, but makes sense if you read it) including the code for the connection would look like:
<?php
// Establish connection (on demand)
$db = new PdoHelper(function(){
$db_server = 'localhost';
$db_port= '3306';
$db_name = 'your_database';
$db_user = 'your_username';
$db_pass = 'your_password';
$dsn = 'mysql:host='.$db_server.';dbname='.$db_name.';port='.$db_port;
$driver_options = array(
PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES 'utf8'",
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
);
$dbh = new PDO( $dsn, $db_user, $db_pass, $driver_options );
return $dbh;
});
// Make a blank sample to have default values for row keys
$default_row = array(
'a'=>null,
'b'=>null,
'c'=>null,
);
// The rows that we want to insert, with columns in the wrong order and nonsense
$rows = array(
array(
'b'=>'a2',
'c'=>'a3',
),
array(
'c'=>'b3',
'b'=>'b2',
),
array(
'b'=>'c2',
'c'=>'c3',
'nonsense'=>'boo',
),
);
// The actual insert query
// INSERT INTO `test_table` (`a`,`b`,`c`) VALUES (null,'a2','a3'), (null,'b2','b3'), (null,'c2','c3')
$db->insertRows('test_table', $default_row, $rows);
// The class that does it all
class PdoHelper {
private $db, $factory;
public function __construct($factory)
{
$this->factory = $factory;
}
public function connect()
{
$cb = $this->factory;
$this->db = $cb();
}
public function release()
{
$this->db = null;
}
public function implyConnect()
{
if(!$this->db){
$this->connect();
}
}
public function begin()
{
$this->implyConnect();
if($this->db instanceof PDO){
$this->db->beginTransaction();
}
}
public function commit()
{
$this->implyConnect();
if($this->db instanceof PDO){
$this->db->commit();
}
}
public function prepare($sql, $data=null, $callback=null)
{
$err = null;
$flat_data = array();
if($data){
$flat_data = self::flatten($data);
$sql = preg_replace_callback('/\?/isu', function($v) use (&$data) {
$val = array_shift($data);
if(is_array($val)){
return self::arrayToPlaceholder($val);
}
return '?';
}, $sql);
}
$this->implyConnect();
if($this->db instanceof PDO){
$stmt = $this->db->prepare($sql);
if($stmt instanceof PDOStatement){
$i = 1;
foreach($flat_data as $v) {
if(is_int($v)){
// workaround for a PDO bug with LIMIT ?,?
$stmt->bindValue($i++, $v, PDO::PARAM_INT);
}else{
$stmt->bindValue($i++, $v, PDO::PARAM_STR);
}
}
}
}
if($callback){
return call_user_func_array($callback, array($stmt));
}
return $stmt;
}
public function query($sql)
{
$res = false;
$args = func_get_args();
$data = array();
$callback = null;
if(isset($args[2])){
$data = $args[1];
$callback = $args[2];
}else
if(isset($args[1])){
if(is_callable($args[1])){
$callback = $args[1];
}else{
$data = $args[1];
}
}
$this->implyConnect();
$stmt = $this->prepare($sql, $data);
$res = $stmt->execute();
if($res && $callback && is_callable($callback)){
return call_user_func_array($callback, array($stmt, $this->db));
}
return $stmt;
}
// Helper functions
public function insertRows($table, $default, $rows=array(), $flag=null, $chunk_size=500)
{
if(empty($rows)){
return null;
}
$chunks = array_chunk($rows, $chunk_size);
foreach($chunks as $rows){
$data = array();
$data[] = $this->extend($default, $rows);
// http://stackoverflow.com/questions/1542627/escaping-column-names-in-pdo-statements
$flag = strtolower($flag);
$flags = array(
'ignore'=>'INSERT IGNORE INTO ',
'replace'=>'REPLACE INTO ',
);
$cols = array();
foreach($default as $k=>$v){
$k = str_replace('`', '``', $k);
$cols[] = '`'.$k.'`';
}
$sql = (isset($flags[$flag])?$flags[$flag]:'INSERT INTO ').$table.' ('.implode(',', $cols).') VALUES ?';
if($flag==='update'){
$cols = array();
foreach($default as $k=>$v){
$k = str_replace('`', '``', $k);
$cols[] = '`'.$k.'`=VALUE('.$k.')';
}
$sql .= ' ON DUPLICATE KEY UPDATE '.implode(', ', $cols);
}
$res = $this->query($sql, $data);
if(!$res){
return $res;
}
}
return $res;
}
public function insertRow($table, $default, $row, $flag=null)
{
$rows = array($row);
return $this->insertRows($table, $default, $rows, $flag);
}
// Helper functions
public static function extend($set, $rows)
{
foreach($rows as $k=>$v){
$v = array_intersect_key($v, $set);
$rows[$k] = array_replace($set, $v);
}
return $rows;
}
public static function flatten($x)
{
$d = array();
if(is_array($x)){
foreach($x as $k=>$v){
$d = array_merge($d, self::flatten($v));
}
}else{
$d[] = $x;
}
return $d;
}
public static function arrayToPlaceholder($array, $timeZone=null) {
return implode(',', array_map(function($v) use($timeZone){
if(is_array($v)){
return '('.self::arrayToPlaceholder($v, $timeZone).')';
}
return '?';
}, $array));
}
public function arrayToList($array, $timeZone=null) {
return implode(',',array_map(function($v) use($timeZone){
if(is_array($v)){
return '('.self::arrayToList($v, $timeZone).')';
}
$this->implyConnect();
return $this->escape($v);
},$array));
}
public function escape($val, $stringifyObjects=false, $timeZone=false) {
if(is_null($val)) return 'NULL';
if(is_bool($val)) return ($val) ? 'true' : 'false';
if(is_int($val)) return (string)$val;
if(is_float($val)) return (string)$val;
if (is_array($val)) {
return $this->arrayToList($val, $timeZone);
}
if(is_callable($val)){ return null; } // TODO
$val = preg_replace_callback('/[\0\n\r\b\t\\\'\"\x1a]/um', function($s) {
switch($s) {
case "\0": return "\\0";
case "\n": return "\\n";
case "\r": return "\\r";
case "\b": return "\\b";
case "\t": return "\\t";
case "\x1a": return "\\Z";
default: return "\\".$s;
}
}, $val);
return $this->db->Quote($val);
}
// Debug functions
public function getSQL($sql, $data){
foreach($data as $k=>$v){
if(is_array($v)){
$data[$k] = self::arrayToList($v);
}else{
$this->implyConnect();
$data[$k] = $this->escape($v);
}
}
$sql = preg_replace_callback('/\?/', function($match) use(&$data)
{
return array_shift($data);
}, $sql);
return $sql;
}
}

Is this mysqli wrapper secure against SQL injection?

Here is how a wrapper looks like:
<?php
Class mysqliwrapper{
protected $_mysqli;
protected $_debug;
public function __construct($host, $username, $password, $database, $debug) {
$this->_mysqli = new mysqli($host, $username, $password, $database);
$this->_debug = (bool) $debug;
if (mysqli_connect_errno()) {
if ($this->_debug) {
echo mysqli_connect_error();
debug_print_backtrace();
}
return false;
}
return true;
}
public function q($query) {
if ($query = $this->_mysqli->prepare($query)) {
if (func_num_args() > 1) {
$x = func_get_args();
$args = array_merge(array(func_get_arg(1)),
array_slice($x, 2));
$args_ref = array();
foreach($args as $k => &$arg) {
$args_ref[$k] = &$arg;
}
call_user_func_array(array($query, 'bind_param'), $args_ref);
}
$query->execute();
if ($query->errno) {
if ($this->_debug) {
echo mysqli_error($this->_mysqli);
debug_print_backtrace();
}
return false;
}
if ($query->affected_rows > -1) {
return $query->affected_rows;
}
$params = array();
$meta = $query->result_metadata();
while ($field = $meta->fetch_field()) {
$params[] = &$row[$field->name];
}
call_user_func_array(array($query, 'bind_result'), $params);
$result = array();
while ($query->fetch()) {
$r = array();
foreach ($row as $key => $val) {
$r[$key] = $val;
}
$result[] = $r;
}
$query->close();
return $result;
} else {
if ($this->_debug) {
echo $this->_mysqli->error;
debug_print_backtrace();
}
return false;
}
}
public function handle() {
return $this->_mysqli;
}
}
?>
This works fine:
$w = new mysqliwrapper("localhost","root","","testdb",1);
$r = $w->q("SELECT * FROM `testdb_news` WHERE `id`=? AND `lang`=?","is",16,'en');
However, this does not:
$r = $w->q("INSERT INTO `testdb_news` ('lang','title','content','date') VALUES (?,?,?,?)","ssss","en","NewTitle","NewContent",mktime());
Why? Should I be using ?-s only for SELECT statements? And go for insert like this?
$r = $w->q("INSERT INTO `testdb_news` (lang,title,content,date) VALUES ('en','newTitle','newContent','".mktime()."')");
Is this secure? Is this class actually secure? Thanks!
safe against injections. see this question which has similar questions Parameterized Query

Categories