php pdo: prepare() does not execute but query() does [foreach loop] - php

I'm not sure if the issue is with the prepare() statement itself or with the bindValues, but I cannot figure out why this works as a query() and not as a prepared statement.
$dbh = new PDO("mysql:host=$dbhost", $dbuser, $dbpass, $options);
$dbh->beginTransaction();
$record_data = $dbh->prepare("UPDATE $db.$dbt SET :column = :value WHERE `key` = :key;");
foreach ( $qaPairs as $pair ) {
list($question , $answer) = explode('=', $pair);
echo "$key : $question $answer";
$record_data->bindValue(':column', $question);
$record_data->bindValue(':value', $answer);
$record_data->bindValue(':key', $key);
$record_data->execute();
}
$dbh->commit();
If I replace the $record_data->bindValue…s and the $record_data->execute() with
$dbh->query("UPDATE `$db`.`$dbt` SET `$question`='$answer' WHERE `key`='$key';");
it works.
For troubleshooting, I added the echo statement, and the values printed are just letters and digits and no quoting; also, the database and table names are not quoted/tick'd.
I read in another question that looping causes problems with prepare and bind_. I switched from bindParam to bindValue, but that didn't seem to help…
EDIT: results of var_dump($key,$question,$answer):
string(17) "m3dc78db1e8368428" string(3) "age" string(2) "23" age 23

You cannot bind a table field name. As much as you cannot bind a table name. You'll have to use this code instead:
$dbh = new PDO("mysql:host=$dbhost", $dbuser, $dbpass, $options);
$dbh->beginTransaction();
foreach ( $qaPairs as $pair ) {
list($question , $answer) = explode('=', $pair);
// Initialize $column here… remember to sanitize it!!!
$record_data = $dbh->prepare("UPDATE $db.$dbt SET $question = :value WHERE `key` = :key;");
echo "$key : $question $answer";
$record_data->bindValue(':value', $answer);
$record_data->bindValue(':key', $key);
$record_data->execute();
}
$dbh->commit();
Reference:
Comment on PHP pdo.prepare.php

Did you change the error mode to 'exception' and used try/catch to display possible errors?
Here is how you do it:
<?php
$dbh = new PDO("mysql:host=$dbhost", $dbuser, $dbpass, $options);
$dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
try {
$dbh->beginTransaction();
$record_data = $dbh->prepare("UPDATE $db.$dbt SET :column = :value WHERE `key` = :key;");
foreach ( $qaPairs as $pair ) {
list($question , $answer) = explode('=', $pair);
echo "$key : $question $answer";
$record_data->bindParam(':column', $question);
$record_data->bindParam(':value', $answer);
$record_data->bindParam(':key', $key);
$record_data->execute();
}
$dbh->commit();
} catch(PDOException $e) {
echo $e;
}
?>
I hope this step provides you with more insight.
Furthermore you need to use bindParam(), because the values of the variables are changing on each iteration.

final code:
error_reporting(-1);
$dbh = new PDO("mysql:host=$dbhost", $dbuser, $dbpass, $options);
$dbh->beginTransaction();
foreach ( $qaPairs as $pair ) {
list($question , $answer) = explode('=', $pair);
//var_dump($key,$question,$answer);
try {
$record_data = $dbh->prepare("UPDATE $db.$dbt SET $question = :value WHERE `key` = :key;");
//$record_data->bindParam(':column', $question);
$record_data->bindParam(':value', $answer);
$record_data->bindParam(':key', $key);
//$dbh->query("UPDATE `$db`.`$dbt` SET `$question`='$answer' WHERE `key`='$key';");
//$record_data->execute(array(1=>$question,2=>$answer,3=>$key));
//$record_data->execute(array(':column'=>$question,':value'=>$answer,':key'=>$key));
$record_data->execute();
}
catch(PDOException $e) {
echo $e;
}
}

Related

insert query mysql throws PDO::exec() expects exactly 1 parameter, 2 given

I've pieced together some code I've gleaned from the internet: I'm trying to scan a directory to insert file names and index into MariaDB table. My last hurdle it seems is this PDO error: PDO::exec() expects exactly 1 parameter, 2 given on line 55. I've tagged line(55) with '//error thrown here'.
My novice guess is it doesn't like the parameters escaped in []??
As noted above novice here...
Any insight/help is greatly appreciated. Thanks in advance.
<?php
$host = 'localhost';
$dbname = 'dirdb';
$username = 'root';
$password = '';
// Create connection
try {
$conn = new PDO("mysql:host=$host;dbname=$dbname", $username, $password);
// set the PDO error mode to exception
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
echo "Connected successfully";
} catch(PDOException $e) {
echo "Connection failed: " . $e->getMessage();
}
ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
error_reporting(E_ALL);
$dir = './recipes';
$GLOBALS['I'] = 0; // root folder given index 0
function dirToArray( $dir , $parent) {
$result = array();
$cdir = scandir($dir);
foreach ($cdir as $key => $value) {
if (!in_array($value, array(".", ".."))) {
if (is_dir($dir . DIRECTORY_SEPARATOR . $value)){
$result[$value] = [++$GLOBALS['I']]; // add folder index
$result[$value][] = $parent; // add parent folder index
$result[$value][] = dirToArray($dir . DIRECTORY_SEPARATOR . $value, $GLOBALS['I']);
} else {
$result[] = $value;
}
}
}
return $result;
}
$res = dirToArray($dir, $GLOBALS['I']);
function dirToDb($res, $parentId = 0)
{global $conn;
foreach ($res as $key => $value) {
if (is_array($value)) {
$conn->exec ("insert into sp_files (path, parentId) VALUES (?, ?)", [$key, $parentId]); //error thrown here
dirToDb($value, $conn->fetch("SELECT LAST_INSERT_ID()"));
} else {
$conn->exec ("insert into sp_files (path, parentId) VALUES (?, ?)", [$value, $parentId]);
}
}
}
//$res = dirToArray($dir);
dirToDb($res);
You can't use $conn->exec() to execute a query with parameters. You have to use prepare() to create a statement, then execute the prepared statement.
There's also no $conn->fetch() method. fetch() is a method of the PDOStatement class, you can use it either with a prepared statement or the result of a query. But you don't need to perform a query to get LAST_INSERT_ID(), PDO has an insertId() method for this.
function dirToDb($res, $parentId = 0) {
global $conn;
$stmt = $conn->prepare("insert into sp_files (path, parentId) VALUES (?, ?)");
foreach ($res as $key => $value) {
$stmt->execute([$key, $parentId]);
if (is_array($value)) {
dirToDb($value, $stmt->insertId);
}
}
}

Array won't print row data

I got this simple PHP code to print a Column from a database and it isn't working unfortually. Any ideas on what to do right?
I've tried to work on the while loop I have in the if statement but no luck
What im trying to get array to print like :
<?php
$input = $_POST['input'];
$servername = "localhost";
$username = "hawk_manager";
$password = "hawk_eyes";
try {
$pdo = new PDO("mysql:host=$servername;dbname=HawkCenter", $username, $password);
// set the PDO error mode to exception
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
} catch(PDOException $e) {
echo "Connection failed: " . $e->getMessage();
}
if ($input == "RoomNumber") {
$query = 'SELECT RoomNumber FROM rooms';
$statement=$pdo->prepare($query);
$statement->execute();
$roomnumbers=$statement->fetchAll(PDO::FETCH_ASSOC);
$statement->closeCursor();
while( $roomnumbers=$statement->fetchAll(PDO::FETCH_ASSOC)){
echo "{$statement['RoomNumber']}";
}
}
$conn = null;
?>
You are doing it wrong, it should be
1. Selecting multiple rows
$data = $pdo->query("SELECT RoomNumber FROM rooms")->fetchAll(PDO::FETCH_ASSOC);
foreach ($data as $row) {
echo $row['RoomNumber ']."<br />\n";
}
2. Prepared Statements::
$stmt = $pdo->prepare("SELECT RoomNumber FROM rooms WHERE id=?");
$stmt->execute([$id]);
$user = $stmt->fetch();
OR
$stmt = $pdo->prepare("$stmt = $pdo->prepare("SELECT RoomNumber FROM rooms LIMIT :limit, :offset");
$stmt->execute(['limit' => $limit, 'offset' => $offset]);
$data = $stmt->fetchAll();
foreach ($data as $row) {
echo $row['RoomNumber']."<br />\n";
}

How to properly select from MSSQL using PHP PDO with query, containing cyrillic symbols?

I'am trying to perform simple SELECT query from PHP PDO to MSSQL database. While query contains cyrillic symbols in WHERE condition, result is empty (if not contains, result return successfully). What can I do to correct query?
putenv('ODBCSYSINI=/etc/');
putenv('ODBCINI=/etc/odbc.ini');
$configODBC = config('database.odbc');
try {
$this->pdo = new PDO('odbc:'. $configODBC['default']['source'], $configODBC['default']['username'], $configODBC['default']['password']);
} catch (PDOException $e) {}
...
$statement = $this->pdo->prepare("SELECT * FROM [DB].[dbo].table WHERE policy_num LIKE '%cyrillic_symbols%'");
$result = $statement->execute();
if ($result) {
while ($out = $statement->fetch()) {
var_dump($out[0]);
}
}
PS. MSSQL version 2012. Data in UTF-8 encoding.
I'll post this as an answer, because it's too long for comment. UTF-8 all the way through, suggested by #RiggsFolly has all the answers. In your case, you need to convert values from CP-1251 from/to UTF-8 . I've made this simple test case, see if this will help you:
T-SQL:
CREATE TABLE CyrillicTable (
[CyrillicText] varchar(200) COLLATE Cyrillic_General_CI_AS
)
INSERT INTO CyrillicTable
(CyrillicText)
VALUES
('Понедельник'),
('Вторник')
PHP (file is UTF-8 encoded, using Notepad++):
<?php
# Connection info
$hostname = 'server\instance,port';
$dbname = 'database';
$username = 'uid';
$pw = 'pwd';
# Connection
try {
$dbh = new PDO("odbc:Driver={SQL Server Native Client 11.0};Server=$hostname;Database=$dbname", $username, $pw);
$dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
} catch( PDOException $e ) {
die( "Error connecting to SQL Server. ".$e->getMessage());
}
# Query
try {
echo "Query"."<br>";
$sql = "SELECT * FROM dbo.[CyrillicTable] WHERE CyrillicText LIKE '%".iconv('UTF-8', 'CP1251', 'онед')."%'";
$stmt = $dbh->query($sql);
while ($row = $stmt->fetch( PDO::FETCH_ASSOC )) {
foreach($row as $name => $value) {
echo $name.": ".iconv('CP1251', 'UTF-8', $value)."<br>";
}
}
echo "<br>";
} catch( PDOException $e ) {
die( "Error executing query: ".$e->getMessage());
}
$stmt = null;
# Query
try {
echo "Prepared query"."<br>";
$sql = "SELECT * FROM dbo.[CyrillicTable] WHERE CyrillicText LIKE ?";
$stmt = $dbh->prepare($sql);
$text = 'орни';
$text = "%$text%";
$text = iconv('UTF-8', 'CP1251', $text);
$stmt->bindParam(1, $text, PDO::PARAM_STR);
$stmt->execute();
while ($row = $stmt->fetch( PDO::FETCH_ASSOC )) {
foreach($row as $name => $value) {
echo $name.": ".iconv('CP1251', 'UTF-8', $value)."<br>";
}
}
echo "<br>";
} catch( PDOException $e ) {
die( "Error executing stored procedure: ".$e->getMessage());
}
$stmt = null;
# End
$dbh = null;
?>
Notes:
Consider using parameterized query.

Add query results to arrary PDO

I am trying to add query results to an array. My while statement works but I am not getting anything in my array. Here is my code:
$res=$pdo->query("select * from questions where category_id='$category' ORDER BY RAND()");
$rows = $res->rowCount();
if ($rows < 1){
echo "There is no question in the database";
exit();}
$questionsArray = array();
while ($item = $res->fetch(PDO::FETCH_ASSOC)){
$questionsArray[] = $item;
echo "There should be some info here<br>";
}
You might want to consider something like this, with thru PDO prepared statements.
Also, a while loop with a fetch is bad and slow and was good 15 years ago with MySQL.
Here is the proper way to do it.
define("SQLHOST", "127.0.0.1");
define("SQLUSER", "user");
define("SQLPASS", "password");
define("SQLSGBD", "database");
try {
$con = new PDO('mysql:host=' . SQLHOST . ';dbname=' . SQLSGBD . ';charset=UTF8', SQLUSER, SQLPASS);
$con->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
} catch (PDOException $e) {
var_dump('Connection failed: ' . $e->getMessage());
}
$categories = ['A', 'B', 'C'];
$questionsArray = array();
$stmt = $con->prepare("select * from questions where category_id=? ORDER BY RAND()");
foreach ($categories as $key => $cat) {
$stmt->bindParam(1, $cat, PDO::PARAM_STR);
$stmt->execute();
$obj = $stmt->fetchall(PDO::FETCH_ASSOC);
if (count($obj) !== 0) {
foreach ($obj as $key2 => $item) {
$questionsArray[] = [$cat => $item];
}
}
}

How to pass varibles in prepared statement function?

I have a prepared statement function for INSERT, I got this function in this forum. but I don't know how to pass variables/array to this function. I am new at this, some help would be really useful.
I want somehing like this:
$obj->insert_data($parameter)
I have listed the function below..
function insert_datas($array) {
$placeholders = array_fill(0, count($array), '?');
$keys = $values = array();
foreach($array as $k => $v) {
$keys[] = $k;
$values[] = !empty($v) ? $v : null;
}
$stmt = self::$mysqli->stmt_init();
$query = 'INSERT INTO `'.DB_TABLE_PAGES.'` '.
'('.implode(',', $keys).') VALUES '.
'('.implode(',', $placeholders).')';
$stmt->prepare($query);
call_user_func_array(
array($stmt, 'bind_param'),
array_merge(
array(str_repeat('s', count($values))),
$values
)
);
$stmt->execute();
}
Try this, hope this helps!
define('DB_HOST', 'database_host');
define('DB_NAME', 'database_name');
define('DB_USER', 'database_user');
define('DB_PASS', 'database_password');
$dbc = new PDO('mysql:host='. DB_HOST .';dbname='. DB_NAME, DB_USER, DB_PASS);
function insert_datas($array) {
foreach($array as $a) {
$insert_table = "INSERT INTO table (column) VALUES (:column)";
$stmt = $dbc->prepare($insert_table);
$stmt->bindValue(':column', $a['key'], PDO::PARAM_STR);
$stmt->execute();
}
}

Categories