Making the switch to PDO from MySQL in PHP. In the past, when a query was ran and wasn't executed for whatever reason, I was able to send myself an email with the mysql_error() message in the body like so:
$query = "SELECT dogs FROM animals";
$res = mysql_query($query);
if (!$res) {
$error = "Error Message: " . mysql_error();
mail("my#email.com","Database Error",$error);
}
From that I would be alerted by an emil when something was wrong with the database on a website.
My PDO setup is as follows:
setAttribute(PDO::ATTR_EMULATE_PREPARES,false);
setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_WARNING);
I have a try catch in the PDO connection itself but I would like to get error messages for prepare and execute as they happen like so:
$query = "SELECT cats FROM animals";
$sql = $pdo->prepare($query);
if (!$sql->execute()) {
$error = "Error Message: " . (pdo error message here);
mail("my#email.com","Database Error",$error);
}
Any ideas on how to assign PDO error messages in an email subject? I'm able to get a logical error message if a prepare fails be using errorInfo() but on execute errors(such as invalid parameter counts for arrays), I can't seem to get an error message.
Thanks for any and all help.
Use try/catch
try {
$sql->execute();
} catch (PDOException $e) {
$e->getMessage(); // This function returns the error message
}
You can use:
$query = "SELECT cats FROM animals";
$sql = $pdo->prepare($query);
if (!$sql->execute()) {
$arr = $sql->errorInfo();
$error = print_r($arr, true);
mail("my#email.com","Database Error",$error);
}
Related
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()));
}
I'm running through a tutorial where it uses MySQLi but instead I'm using PDO and I have been trying to pin the issue to why I am getting this error:
Fatal error: Call to a member function errorInfo() on string in D:\Program Files (x86)\xampp\htdocs\repos\bla\web\inboxPage.php on line 34
Here is where I am trying to call the errorInfo(), I had previously used mysql_error(); as per tutorial, but this also threw the same error. Before using errorInfo() I was looking around to see if there was a PDO equivelant to mysql_error() which lead me to what you see below - Me thinking it would work. But it didn't.
Tutorials example:
$query = "SELECT id, sender, subject, message FROM messages WHERE reciever='$user'";
$sqlinbox = mysql_query($query);
if(!$sqlinbox)
{
?>
<p><?php print '$query: '.$query.mysql_error();?></p>
<?php
}
My Example:
$sql = 'SELECT id, Sender, Subject, Message FROM privatemessages WHERE Receiver = :receiver';
$stmt = $conn->prepare($sql);
$stmt->bindParam(':receiver', $user);
$stmt->execute();
$result = $stmt->fetch(PDO::FETCH_ASSOC);
if (!$result){
?>
<p><?php print '$sql: '.$sql.errorInfo(); ?></p>
<?php
}
Here is my connection to the database:
$servername = 'localhost';
$user = 'root';
$pass = '';
$database = 'tutor_database';
try {
$conn = new PDO("mysql:host=$servername;dbname=$database", $user, $pass);
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
}
catch (PDOException $e){
echo "Connection failed: " . $e->getMessage();
}
In addition, I did try the first example from the PHP Manual website -> http://php.net/manual/en/pdostatement.errorinfo.php and found that doing so gave me:
PDO::errorInfo():
Notice: Array to string conversion in D:\Program Files (x86)\xampp\htdocs\repos\bla\web\inboxPage.php on line 37
$sql: Array
...instead.
Would appreciate some help on this as I'm clearly failing to see what is happening. Thanks in advance.
In PDO a completely different method for the error reporting have to be used. In short, PDO will report its errors already, without the need to write any code.
So just take out the error reporting part, leaving only
$sql = 'SELECT id, Sender, Subject, Message FROM privatemessages WHERE Receiver = :receiver';
$stmt = $conn->prepare($sql);
$stmt->bindParam(':receiver', $user);
$stmt->execute();
$result = $stmt->fetch(PDO::FETCH_ASSOC);
that's all you need.
Recently looking through some old files and realised that they are now deprecated. I've tried converting them into the newer PDO variant, but I'm stuck on something. Here's the code:
<?php
$team=$_POST['team'];
$user=$_POST['user'];
$dbHandle=new PDO("mysql:host=localhost;dbname=databasename;","user","password",array(PDO::ATTR_EMULATE_PREPARES=>false));
$query=$dbHandle->prepare("INSERT INTO tablename VALUES(?,?,?)");
if(!is_numeric($user)){
echo "Error message 1";
}elseif($user=="123"){
echo "Error message 2";
}else{
$query->execute(array($user,$team,"pending"));
if(mysql_affected_rows()>0){
echo "Success message";
}else{
echo "Error message 3";
}
}
?>
Nothing I've tried seems to get the success message. It looks like most of the code is working, because it always ends up giving me the third error message every time, and I can confirm that nothing has been added to the database. Not shown above are the three lines of code for enabling all PHP error messages, but the page isn't throwing up any such messages.
Also, while I'm at it, I'm still not entirely familiar with PDO, but from the way I understood it, it's much more secure. From what I have above, are there any security risks, and if so, how should I fix them?
EDIT: The code is currently as thus:
<?php
$team=$_POST['team'];
$user=$_POST['user'];
$dbHandle=new PDO("mysql:host=localhost;dbname=databasename;","user","password",array(PDO::ATTR_EMULATE_PREPARES=>false));
$query=$dbHandle->prepare("INSERT INTO tablename VALUES(?,?,?)");
if(!is_numeric($user)){
echo "Error message 1";
}elseif($user=="123"){
echo "Error message 2";
}else{
$query->execute(array($user,$team,"pending"));
if($query->rowCount()>0){
echo "Success message";
}else{
echo "Error message 3";
}
}
?>
<?php
ini_set('display_errors',1);
error_reporting(E_ALL);
$dsn = "mysql:host=localhost;dbname=test;charset=utf8";
$opt = array(
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC
);
$pdo = new PDO($dsn,"user","password", $opt);
$stm = $pdo->prepare("INSERT INTO tablename VALUES(?,?,?)");
$stm->execute(array($_POST['user'],$_POST['team'],"pending"));
echo "Success message";
The problem is that mysql_affected_rows() function is not PDO, you should use ->rowCount() method to know the value of affected rows. Also, I would preffer to add parameters in a separated instruction specifying the correct type with constants like PDO::PARAM_INT and PDO::PARAM_STR, so you can avoid errors:
$query=$dbHandle->prepare("INSERT INTO tablename VALUES(?,?,?)");
if(!is_numeric($user)){
echo "Error message 1";
}elseif($user=="123"){
echo "Error message 2";
}else{
$status = "pending";
$query->bindParam(1, $user, PDO::PARAM_INT);
$query->bindParam(2, $team, PDO::PARAM_STR);
$query->bindParam(3, $status, PDO::PARAM_STR);
$query->execute();
if($query->rowCount() > 0){
echo "Success message";
}else{
echo "Error message 3";
}
}
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.
I'm new to PDO and I wanna do it right from the beginning - I'm going to replace my old mysql_ functions on a site.
Have I got it right?:
Should I put the connection code in a try/catch and save it to a file, and include it on top of the page. Then put the queries in try/catch as well.
Or:
Should I put the connection code in a file and include it in the in the top of the try/catch statement above the query?
ver1:
include('pdo.php'); // try/catch in file
try {
$stmt = $conn->prepare('SELECT * FROM myTable WHERE id = :id');
$stmt->execute(array('id' => $id));
while($row = $stmt->fetch()) {
print_r($row);
}
} catch(PDOException $e) {
echo 'ERROR: ' . $e->getMessage();
}
ver2:
try {
include('pdo.php'); // no try/catch in file
$stmt = $conn->prepare('SELECT * FROM myTable WHERE id = :id');
$stmt->execute(array('id' => $id));
while($row = $stmt->fetch()) {
print_r($row);
}
} catch(PDOException $e) {
echo 'ERROR: ' . $e->getMessage();
}
Or should I put the try/catch in both places?
You should do both and even more :
Set an error handler that displays a message to the user and stops the PHP (see set_error_handler)
When you initiate the connexion, add a try/catch and throw an error if you catch an exception. Your website won't run without database connection i guess.
Do a try/catch around your queries to recover gracefully from error (when you can)