Take this simple piece of code:
$dbhost = "host";
$dbuser = 'user';
$dbpass = "password";
$dbname = "database";
$query = "SELECT (col1, col2 from columnstable";
$mysqli = new Mysqli($dbhost, $dbuser, $dbpass, $dbname);
$result = $mysqli->query($query);
$data = $result->fetch_all();
foreach($data as $row) {
echo $row[0].','.$row[1]."<br>\n";
}
$mysqli->close();
It will fail because there's a syntax error in the query. How will the program know? It won't.
The code will attempt to execute the query, but MySQL will complain about the broken syntax and $mysqli->query()
will return false
.
The first you'll know about it is when PHP complains with a cryptic message like Fatal error: Call to a member function fetch_all() on boolean.
Checking for errors
The most obvious thing to do is check the result of the call to mysqli->query()
. If it returns false
then the program can take some action. That's a good start, but it doesn't tell you what the error actually is. To get that information we need to look at $mysqli->error
// Database credentials omitted for brevity
$query = "SELECT (col1, col2 from columnstable";
$mysqli = new Mysqli($dbhost, $dbuser, $dbpass, $dbname);
// Check that our connection succeeded
if ($mysqli->connect_error) {
echo $mysqli->connect_error."<br>\n";
exit;
}
$result = $mysqli->query($query);
// Check for an error in our query
if ($result !== false) {
$data = $result->fetch_all();
foreach ($data as $row) {
echo $row[0] . ',' . $row[1] . "<br>\n";
}
} else {
echo "MySQL error: ".$mysqli->error."<br>\n";
exit;
}
$mysqli->close();
exit;
Better! Now we see the error message provided by MySQL: Error #1064 - You have an error in your SQL syntax...
However, it's clear that this will quickly require a great deal of error checking, and a substantial amount of code to handle errors. Since most MySQL errors are likely to be fatal, there has to be a better way.
Exceptions and MySQL errors
A simple call to mysqli_report()
with the right flags set will cause MySQL failures to throw an exception instead of just returning a false
value.
Updating our code again we now have:
$query = "SELECT col1 col2 from columnstable";
mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
$mysqli = new Mysqli($dbhost, $dbuser, $dbpass, $dbname);
// Check that our connection succeeded
if ($mysqli->connect_error) {
echo $mysqli->connect_error."
\n";
exit;
}
try {
$result = $mysqli->query($sql);
$data = $result->fetch_all();
$mysqli->close();
catch (Exception $e) {
echo "An SQL error occurred: ".$e->getMessage();
}
exit;
These examples use MySQLi. What about PDO?
Naturally, as PDO is a more recent and more sophisticated interface, error reporting is built in. You can test the return value of a call to PDO::query()
or PDO::execute()
exactly as you would for MySQLi.
And, of course, you can enable exceptions:
// Database Credntials omitted for brevity
$dsn = "mysql:host=$dbhost;dbname=$dbname";
try {
$PDO = new PDO($dsn, $dbuser, $dbpass); // PDO always throws an exception if it fails here
// Tell PDO to throw exceptions if errors occur
$PDO->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$query = "SELECT (col1, col2 from columnstable";
$result = $PDO->query($query);
$data = $result->fetchAll();
foreach($data as $row) {
echo $row[0] . ',' . $row[1] . "<br>\n";
}
} catch (Exception $e) {
echo "An SQL error occurred: ".$e->getMessage();
}
exit;