Error Checking for PDO Prepared Statements [duplicate] - php

This question already has answers here:
Why does this PDO statement silently fail?
(2 answers)
Closed 5 years ago.
I'm trying to create proper error handling for queries on a MySQL database using PDO prepared statements. I want the program to exit the moment an error in the prepared statement process is detected. Taking advantage of the fact that each step in the PDO prepared statement process returns False on failure, I threw together this repugnant hack:
global $allFields;
global $db;
global $app;
//dynamically append all relevant fields to query using $allFields global
$selectQuery = 'SELECT ' . implode($allFields, ', ') .
' FROM People WHERE ' . $fieldName . ' = :value';
//prepared statement -- returns boolean false if failure running query; run success check
$success = $selectQueryResult = $db->prepare($selectQuery);
checkSuccess($success);
$success = $selectQueryResult->bindParam(':value', $fieldValue, PDO::PARAM_STR);
checkSuccess($success);
$success = $selectQueryResult->execute();
checkSuccess($success);
with checkSuccess() doing the following:
function checkSuccess($success) {
if ($success == false) {
//TODO: custom error page.
echo "Error connecting to database with this query.";
die();
}
}
Two things. First, this is horribly verbose and stupid. There must be a better way. Obviously I could store the booleans in an array or something to take out a line or 2 of code, but still.
Second, is it even necessary to check these values, or should I just check the result after I perform this line of code:
$result = $selectQueryResult->fetch(PDO::FETCH_ASSOC);
I already have code that does this:
if ($result) { //test if query generated results
// do successful shit
}
else {
echo "404";
$app->response()->status(404); //create 404 response header if no results
As much as I try to break the prepared statement process by inserting weird, mismatched, or lengthy queries, my program always makes it to the $result assignment without returning false on any of the functions where I run checkSuccess(). So maybe I don't need to be checking the above logic at all? Keep in mind that I check for a successful database connection earlier in the program.

I preffer setting the error mode to throwing exceptions like this:
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
right after I connect to the database. So every problem will throw an PDOException
So your code would be:
$selectQuery = '
SELECT
' . implode($allFields, ', ') . '
FROM
People
WHERE
' . $fieldName . ' = :value
';
try
{
$selectQueryResult = $db->prepare($selectQuery);
selectQueryResult->bindParam(':value', $fieldValue);
$selectQueryResult->execute();
}
catch(PDOException $e)
{
handle_sql_errors($selectQuery, $e->getMessage());
}
where the function would be:
function handle_sql_errors($query, $error_message)
{
echo '<pre>';
echo $query;
echo '</pre>';
echo $error_message;
die;
}
In fact I am using a general function that also has something like
$debug = debug_backtrace();
echo 'Found in ' . $debug[0]['file'] . ' on line ' . $debug[0]['line'];
to tell me where was the problem if I am running multiple queries

You have to catch PDOException:
try {
//your code/query
} catch (PDOException $e) {
//Do your error handling here
$message = $e->getMessage();
}
PDOException

Related

Using .php to write data to database

Can someone point the fault in this code? I'm unable to update data to the database. We are sending a text message to the server, and this file here decodes and sets it in the database. But this case over here is not working for some reason. I checked and tried to troubleshoot, but couldn't find a problem.
case 23:
// Gather Variables
$Message = preg_replace("/\s+/","%20", $Message);
$UnixTime = time();
$cycle = explode(":", $Message);
$machine_press = $cycle[0];
$machine_pct_full = $machine_press/20;
$machine_cycles_return = $cycle[1];
$machine_cycles_total = $cycle[2];
// Build SQL Statement to update static values in the machine table
$sql = "UPDATE `machines` SET `machine_last_run`=".$UnixTime.",`machine_press`=".$machine_press.",`machine_pct_full`=".$machine_pct_full.",`machine_cycles_return`=".$machine_cycles_return.",`machine_cycles_total`=".$machine_cycles_total." WHERE `machine_serial`='$MachSerial'";
// Performs the $sql query on the server to update the values
if ($conn->query($sql) === TRUE) {
// echo 'Entry saved successfully<br>';
} else {
echo 'Error: '. $conn->error;
}
$sql = "INSERT INTO `cycles` (`cycle_sequence`,`cycle_timestamp`,`cycle_did`,`cycle_serial`,`cycle_03_INT`,`cycle_14_INT`,`cycle_15_INT`,`cycle_18_INT`)";
$sql = $sql . "VALUES ($SeqNum,$UnixTime,'$siteDID','$MachSerial',$machine_press,$machine_cycles_total,$machine_cycles_return,$machine_pct_full)";
// Performs the $sql query on the server to insert the values
if ($conn->query($sql) === TRUE) {
// echo 'Entry saved successfully<br>';
} else {
echo 'Error: '. $conn->error;
}
break;
More information is required to help you out with your issue.
First, to display errors, edit the index.php file in your Codeigniter
project, update where it says
define('ENVIRONMENT', 'production');
to
define('ENVIRONMENT', 'development');
Then you'll see exactly what the problem is. That way you can provide the information needed to help you.
I just saw that you are inserting strings when not wrapping them in apostrophe '. So you queries should be:
$sql = "UPDATE `machines` SET `machine_last_run`='".$UnixTime."',`machine_press`='".$machine_press."',`machine_pct_full`='".$machine_pct_full."',`machine_cycles_return`='".$machine_cycles_return."',`machine_cycles_total`='".$machine_cycles_total."' WHERE `machine_serial`='$MachSerial'";
and
$sql = "INSERT INTO `cycles` (`cycle_sequence`,`cycle_timestamp`,`cycle_did`,`cycle_serial`,`cycle_03_INT`,`cycle_14_INT`,`cycle_15_INT`,`cycle_18_INT`)";
$sql = $sql . " VALUES ('$SeqNum','$UnixTime','$siteDID','$MachSerial','$machine_press','$machine_cycles_total','$machine_cycles_return','$machine_pct_full')";
For any type of unknown problems I can recommend turning on PHP and SQL errors and use a tool called postman that i use to test my apis. You can mimic requests with any method, headers and parameters and send an "sms" just like your provider or whatever does to your API. You can then see the errors your application throws.
EDIT
I tested your script using a fixed version with ' and db.
$Message = "value1:value2:value3";
$MachSerial = "someSerial";
$SeqNum = "someSeqNo";
$siteDID = "someDID";
$pdo = new PDO('mysql:host=someHost;dbname=someDb', 'someUser', 'somePass');
// Gather Variables
$Message = preg_replace("/\s+/","%20", $Message);
$UnixTime = time();
$cycle = explode(":", $Message);
$machine_press = $cycle[0];
$machine_pct_full = (int)$machine_press/20; // <----- Note the casting to int. Else a warning is thrown.
$machine_cycles_return = $cycle[1];
$machine_cycles_total = $cycle[2];
// Build SQL Statement to update static values in the machine table
$sql = "UPDATE `machines` SET `machine_last_run`='$UnixTime',`machine_press`='$machine_press',`machine_pct_full`='$machine_pct_full',`machine_cycles_return`='$machine_cycles_return',`machine_cycles_total`='$machine_cycles_total' WHERE `machine_serial`='$MachSerial'";
try {
$pdo->query($sql);
} catch (PDOException $e) {
echo 'Query failed: ' . $e->getMessage();
}
$sql = "INSERT INTO `cycles` (`cycle_sequence`,`cycle_timestamp`,`cycle_did`,`cycle_serial`,`cycle_03_INT`,`cycle_14_INT`,`cycle_15_INT`,`cycle_18_INT`)";
$sql = $sql . "VALUES ('$SeqNum','$UnixTime','$siteDID','$MachSerial','$machine_press','$machine_cycles_total','$machine_cycles_return','$machine_pct_full')";
try {
$pdo->query($sql);
} catch (PDOException $e) {
echo 'Query failed: ' . $e->getMessage();
}
It totally works. Got every cycle inserted and machines updated. Before i fixed it by adding wrapping ' i got plenty of errors.
Alright so this is the solution:
i replaced the line:
$Message = preg_replace("/\s+/","%20", $Message);
with:
$Message = preg_replace("/\s+/","", $Message);
This removes all blank spaces in my text message and makes it a single string before breaking and assigning it to different tables in the database.
I understand this wasnt really a problem with the script and no one around would have known the actual problem before answering. and thats why i am posting the solution just to update the team involved here.

PDO PHP select distinct query not working for mssql

I've got a website that is pulling data from my MSSQL Server. I am using functions to build tables for reports. Here's what I've got:
function BeginTable($rowCount,$headings,$searchValue,$ReportName,$OneButton,$NewSearch)
{
try{
$StateSelectSQL = "select distinct State from pmdb.MaterialTracking where State is not null";
var_dump($StateSelectSQL);echo " What!<br>";
$getSelect = $conn->query($StateSelectSQL);
var_dump($getSelect);echo " When!<br>";
$StateSelectNames = $getSelect->fetchALL(PDO::FETCH_ASSOC);
var_dump($StateSelectNames);echo " Where!<br>";
}
catch(Exception $e)
{
echo "Something went wrong";
die(print_r($e->getMessage()));
}
I tried this too:
try{
$StateSelectSQL = "select distinct State from pmdb.MaterialTracking where State is not null";
var_dump($StateSelectSQL);echo " What!<br>";
$getSelect = $conn->prepare($StateSelectSQL);
$getSelect->execute();
//$getSelect = $conn->query($StateSelectSQL);
//var_dump($getSelect);echo " When!<br>";
$StateSelectNames = $getSelect->fetchALL(PDO::FETCH_ASSOC);
var_dump($StateSelectNames);echo " Where!<br>";
}
catch(Exception $e)
{
echo "Something went wrong<br>";
die( print_r( $e->getMessage()));
}
The second and third var_dump's never show anything and the rest of the code (not shown here) doesn't get run. If I comment out the $getSelect and $StateSelectNames lines (with the var_dump's under them) then everything else works.
Here is my DBConn.php file that is included above the Function:
$conn = new PDO("sqlsrv:server=$servername;database=$dbname", $username,$password);
//set the PDO error mode to exception
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$conn->setAttribute(PDO::SQLSRV_ATTR_QUERY_TIMEOUT, 10);
What is wrong with the line $getSelect = $conn->query($StateSelectSQL); I can't figure it out. I tried using it later in my foreach like this:
foreach($conn->query($StateSelectSQL) as $StateName)
But that doesn't work either. It again stops at this line and doesn't go any further. The only thing I can think of is that my SQL is messed up, but when I run it in SSMS it works fine!
What's going on?
Try preparing and executing your SQL before using fetchAll. Also consider enabling exception mode if you haven't already and wrapping your statement in a try catch - this should flag any issues (e.g. your applications database user not having permission to access the schema, or syntax error etc)
Exceptions:
See this stack overflow post for info about how to enable
And for your code:
try {
$sql = "
SELECT DISTINCT State
FROM pmdb.MaterialTracking
WHERE State IS NOT NULL
";
$sth = $conn->prepare($sql);
$sth->execute();
$rowset = $sth->fetchAll(PDO::FETCH_ASSOC);
print_r($rowset);
} catch PDOException($err) {
echo "Something went wrong".
echo $err;
}
I have figured it out after pulling my hair out all day! I had to include my DBConn.php inside the function. After this it worked. I don't know why that mattered since it is included at the beginning of the file. If there is anyone who can explain why that is i'd be grateful!
It now looks like this:
function BeginTable($rowCount,$headings,$searchValue,$ReportName,$OneButton,$NewSearch)
{
try{
include("DBConn.php");
$SelectSQL = "select distinct State from pmdb.MaterialTracking where State is not null order by State";
$getSelect = $conn->prepare($SelectSQL);
$getSelect->execute();
$StateSelectNames = $getSelect->fetchALL(PDO::FETCH_ASSOC);
}
catch(Exception $e)
{
echo "Something went wrong<br>";
die( print_r( $e->getMessage()));
}

Connecting to MYSQL using php

I am trying to connect to MYSQL using php, but when I use the following command:
$link=mysql_connect("localhost","root","password");
and echo $link, it gives me Resource id #98. What does this mean? Am I not connected?
Okay, I guess it sounds like the connection is okay. Now, with the following code, I am not seeing any changes in the mysql database. Why could that be?
<?php
$conn=new mysqli("localhost","root","password","database");
$sql="INSERT INTO chat_active (user, time)
VALUES('John', '1234')";
?>
What makes you think you are not connected?
According to the docs, mysql_connect()
[r]eturns a MySQL link identifier on success or FALSE on failure.
Since it did not return FALSE, but rather a resource identifier, that means the connection was successful.
Also note that the mysql extension is deprecated since PHP 5.5.0 as MortimerCat pointed out. Instead you should look into the MySQLi or the PDO extension.
"Now, with the following code, I am not seeing any changes in the mysql database. Why could that be?"
As per your edit which you are now using mysqli_ to connect with, and that you're saying that you're not seeing any changes in your database, is because:
You're not passing the DB connection to your query and it is required when using mysqli_.
Rewrite, with a few more goodies:
<?php
$conn=new mysqli("localhost","root","password","database");
// Check if you've any errors when trying to access DB
if ($conn->connect_errno) {
printf("Connect failed: %s\n", $conn->connect_error);
exit();
}
$sql="INSERT INTO chat_active (user, time) VALUES ('John', '1234')";
$result = $conn->query($sql);
// Check if you've any errors when trying to enter data in DB
if (!$result)
{
throw new Exception($conn->error);
}
else{
echo "Success";
}
Read the manual http://php.net/manual/en/mysqli.query.php
Once you've grasped that, get to know mysqli with prepared statements, or PDO with prepared statements, they're much safer.
References:
http://php.net/manual/en/book.mysqli.php
http://php.net/manual/en/mysqli.query.php
http://php.net/manual/en/mysqli.error.php
http://php.net/manual/en/language.exceptions.php
Footnotes:
Your column names user, time suggests that you're trying to enter a string and what appears to be and to be intended as "time" and that the user column is set to varchar.
Make sure that you haven't setup your time column other than a datetime-related type, otherwise MySQL may complain about that.
MySQL stores dates as YYYY-mm-dd as an example.
Visit https://dev.mysql.com/doc/refman/5.0/en/datetime.html in regards to different date/time functions you can use.
MySQL references:
https://dev.mysql.com/doc/refman/5.0/en/char.html
https://dev.mysql.com/doc/refman/5.0/en/data-types.html
https://dev.mysql.com/doc/refman/5.0/en/datetime.html
You yould use mysqli or PDO.
Here's a connection example with PDO:
<?php
$dbuser = 'user';
$dbpasswd = 'passwd';
$dbname = 'dbname';
try {
$gbd = new PDO("mysql:host=localhost;dbname=$dbname;charset=utf8", $dbuser, $dbpasswd);
$gbd->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
}
catch(PDOException $e) {
echo $e->getMessage();
}
PDO CRUD examples:
//INSERT
try {
$sentence = $gbd->prepare("INSERT INTO table (param1, param2) VALUES (:param1, :param2)");
$sentence->bindParam(':param1', $param1);
$sentence->bindParam(':param2', $param2);
$sentence->execute();
}
catch (PDOException $e) {
echo 'Query failed: ' . $e->getMessage();
}
//SELECT
try {
$sentence = $gbd->prepare("SELECT param1,param2 FROM table WHERE param1 = :param1 AND param2 = :param2)");
$sentence->bindParam(':param1', $param1);
$sentence->bindParam(':param2', $param2);
$sentence->execute();
while ($row = $sentence->fetch(PDO::FETCH_ASSOC)){ //Also available FETCH_NUM,FETCH_BOTH AND OTHERS
$result['param1'] = $row['param1'];
$result['param2'] = $row['param2'];
}
}
catch (PDOException $e) {
echo 'Query failed: ' . $e->getMessage();
}
//UPDATE
try {
$sentence = $gbd->prepare("UPDATE table SET param1 = :param1, param2 = :param2)");
$sentence->bindParam(':param1', $param1);
$sentence->bindParam(':param2', $param2);
$sentence->execute();
}
catch (PDOException $e) {
echo 'Query failed: ' . $e->getMessage();
}
//DELETE
try {
$sentence = $gbd->prepare("DELETE table WHERE param1 = :param1 AND param2 = :param2)");
$sentence->bindParam(':param1', $param1);
$sentence->bindParam(':param2', $param2);
$sentence->execute();
}
catch (PDOException $e) {
echo 'Query failed: ' . $e->getMessage();
}
And here's PDO manual
http://php.net/manual/en/book.pdo.php
u are not executing that query.u are only declaring that query.
for execution do--
$conn->query($qry);
it will,execute ur query.

running a mysql stored procedure from php

I must be doing something wrong in this code....
<?
$codeid=$_GET["codeid"];
$tablecode=$_GET["tablecode"];
$description=$_GET["description"];
$code=$_GET["code"];
$groupcode=$_GET["groupcode"];
$t1=$_GET["t1"];
$t2=$_GET["t2"];
$t3=$_GET["t3"];
$mysqli = new mysqli(dbhost,dbuser,dbpass,dbc);
if ($mysqli->connect_error) {
die('Connect Error (' . $mysqli->connect_errno . ') ' . $mysqli->connect_error);
}
$q="call spUpdateCodeTable(?,?,?,?,?,?,?,?)";
$stmt = $mysqli->prepare($q);
$stmt->bind_param($codeid,$tablecode,$description,$code,$groupcode,$t1,$t2,$t3);
$stmt->execute();
mysql_close($mysqli);
?>
Absolutely nothing happens...no error message or any other indication of a problem. It just does not run the procedure. (it's an update/insert routine).
I am using this URL...
updateCodeTable.php?codeid=0&codetable=TABLE&desription=testing2%20entry&code=TEST1&groupcode=gcode&t1=t1&t2=t2&t3=t3
...but, if I run the this query in phpMyAdmin, it runs perfectly....
call spUpdateCodeTable(0,'TABLE','testing2','TEST1','group','','','');
I could include the stored procedure code, but it runs fine anytime I run it directly, but just not running successfully from my php code.
Each mysqli* function/method can fail. Either test the return values and/or switch the reporting mechanism to exceptions, see http://docs.php.net/mysqli-driver.report-mode
<?php
// probably better done with http://docs.php.net/filter but anyway ...just check whether all those parameters are really there
// you are positive that GET is the correct method for this action?
if ( !isset($_GET["codeid"], $_GET["tablecode"], $_GET["description"], $_GET["code"], $_GET["groupcode"], $_GET["t1"], $_GET["t2"], $_GET["t3"]) ) {
// die() is such a crude method
// but bare me, it's just an example....
// see e.g. http://docs.php.net/trigger_error
die('missing parameter');
}
else {
$mysqli = new mysqli(dbhost,dbuser,dbpass,dbc);
if ($mysqli->connect_error) {
die('Connect Error (' . $mysqli->connect_errno . ') ' . $mysqli->connect_error);
}
$q="call spUpdateCodeTable(?,?,?,?,?,?,?,?)";
$stmt = $mysqli->prepare($q);
if ( !$stmt ) {
// $mysqli->error has more info
die('prepare failed');
}
// you have to provide the format of each parameter in the first parameter to bind_param
// I just set them all to strings, better check that
if ( !$stmt->bind_param('ssssssss', $_GET['codeid'], $_GET['tablecode'], $_GET['description'], $_GET['code'], $_GET['groupcode'], $_GET['t1'], $_GET['t2'], $_GET['t3']) ) {
// $stmt->error has more info
die('bind failed');
}
if ( !$stmt->execute() ) {
// $stmt->error has more info
die('execute failed');
}
}
May you have a try to this?
mysqli->query("call spUpdateCodeTable($codeid,'$tablecode',
'$description','$code','$groupcode','$t1','$t2','$t3')");

How to Get Error Details From MySQL Stored Procedure

I am calling a mysql stored procedure using PDO in PHP
try {
$conn = new PDO("mysql:host=$host_db; dbname=$name_db", $user_db, $pass_db);
$stmt = $conn->prepare('CALL sp_user(?,?,#user_id,#product_id)');
$stmt->execute(array("user2", "product2"));
$stmt->setFetchMode(PDO::FETCH_COLUMN, 0);
$errors = $stmt->errorInfo();
if($errors){
echo $errors[2];
}else{
/*Do rest*/
}
}catch(PDOException $e) {
echo "Error : ".$e->getMessage();
}
that return below error because the name of the field in insert query was given wrong
Unknown column 'name1' in 'field list'
So i want to know if this is possible to get detailed error information something like:-
Unknown column 'Tablename.name1' in the 'field list';
that could tell me what column of which table is Unknown.
while creating the pdo connection, pass options like error mode and encoding:
The PDO system consists of 3 classes: PDO, PDOStatement & PDOException. The PDOException class is what you need for error handling.
Here is an example:
try
{
// use the appropriate values …
$pdo = new PDO($dsn, $login, $password);
// any occurring errors wil be thrown as PDOException
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$ps = $pdo->prepare("SELECT `name` FROM `fruits` WHERE `type` = ?");
$ps->bindValue(1, $_GET['type']);
$ps->execute();
$ps->setFetchMode(PDO::FETCH_COLUMN, 0);
$text = "";
foreach ($ps as $row)
{
$text .= $row . "<br>";
}
// a function or method would use a return instead
echo $text;
} catch (Exception $e) {
// apologise
echo '<p class="error">Oops, we have encountered a problem, but we will deal with it. Promised.</p>';
// notify admin
send_error_mail($e->getMessage());
}
// any code that follows here will be executed
I found this to be helpful for me. "error_log" prints to the php error log but you can replace with whatever way you'd like to display the error.
} catch (PDOException $ex){
error_log("MYSQL_ERROR"); //This reminds me what kind of error this actually is
error_log($ex->getTraceAsString()); // will show the php file line (and parameter
// values) so you can figure out which
// query/values caused it
error_log($ex->getMessage()); // will show the actual MYSQL query error
// e.g. constraint issue
}
p.s. I know this is a bit late but maybe it can help someone.

Categories