I have
<?php
error_reporting(E_ALL);
ini_set('display_errors', 1);
require_once "configuration.php";
header('Content-Type: application/json');
try
{
$mysqli = new mysqli(MYSQL_SERVER, MYSQL_USERNAME, MYSQL_PASSWORD, MYSQL_DATABASE);
$mysqli->set_charset("utf8");
} catch (Exception $e) {
echo json_encode(
array(
'msg' => $e->getMessage()
)
);
}
And if mysqli is not enabled then it does not catch the error:
Fatal error: Uncaught Error: Class 'mysqli' not found in C:\test\db_connect.php:8
Stack trace:
#0 C:\test\getContacts.php(2): require_once()
#1 {main} thrown in C:\test\db_connect.php on line 8
What can I do so that it catches the error?
I have tried this one but it didn't work:
<?php
error_reporting(E_ALL);
ini_set('display_errors', 1);
require_once "configuration.php";
header('Content-Type: application/json');
try
{
if(!extension_loaded('mysqli'))
{
throw new Exception('mysqli is not enabled');
}
$mysqli = new mysqli(MYSQL_SERVER, MYSQL_USERNAME, MYSQL_PASSWORD, MYSQL_DATABASE);
$mysqli->set_charset("utf8");
} catch (Exception $e) {
echo json_encode(
array(
'msg' => $e->getMessage()
)
);
}
This one does not halt, continues to execute the script.
{"msg":"mysqli is not enabled"}
Notice: Undefined variable: mysqli in C:\test\getContacts.php on line 99
Fatal error: Uncaught Error: Call to a member function query() on null in C:\test\getContacts.php:99
Stack trace:
#0 {main}
thrown in C:\test\getContacts.php on line 99
It's odd that it wouldn't be installed but if you're rolling your own I guess it could be omitted. I would check to see if the procedural functions exist
if(!function_exists('mysqli_connect')) {
throw new Exception('mysqli is not enabled');
}
As the question is tagged php-7: An error in php 7 can be caught but it does not inherit from Exception so you have to catch them differently:
...
} catch (Error $e) {
^^^^^ Not Exception
echo json_encode(
array(
'msg' => $e->getMessage()
)
);
// stop execution
exit;
}
See the manual for more information about error handling in php 7.
Related
I have Sentry keeping track of uncaught exceptions in my PHP application, and I noticed a peculiar uncaught exception from PDO. The code looks like this:
/**
* #return boolean TRUE if the connection to the database worked; FALSE otherwise.
*/
public function verifyDatabase() {
try{
$this->pdo->query('SELECT 1');
return true;
}
catch (\PDOException $e) {
echo 'Lost connection to database: ' . $e->getMessage() . PHP_EOL;
return false;
}
}
This should catch errors like "MySQL server has gone away", and it indeed works on my development machine. However, Sentry recently recorded this error:
ErrorException
PDO::query(): MySQL server has gone away
According to sentry, this was thrown by the $this->pdo->query('SELECT 1'); statement above. Errors like this should have been caught by the try/catch. Why is PDO throwing an ErrorException rather than a PDOException?
I can't reproduce an ErrorException.
$pdo = new PDO('mysql:host=127.0.0.1;dbname=test', ..., ...);
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
sleep(20); // during this sleep, I stop my MySQL Server instance.
$result = $pdo->query("SELECT 1");
Output:
Warning: PDO::query(): MySQL server has gone away
Warning: PDO::query(): Error reading result set's header
Fatal error: Uncaught PDOException: SQLSTATE[HY000]: General error: 2006 MySQL server has gone away
Stack trace:
#0 /Users/bkarwin/Documents/SO/pdo.php(8): PDO->query('SELECT 1')
This shows it throws a PDOException when the server has gone away, not an ErrorException.
Tested with MySQL 5.6.37 and PHP 7.1.23.
I wonder if the code you show in your question is actually the code that is deployed and throwing the exception to Sentry. Perhaps you have some code like:
catch (\PDOException $e) {
throw ErrorException($e->getMessage());
}
Either in your verifyDatabase() function, or else in the code that calls verifyDatabase(). In other words, what does your app do when verifyDatabase() returns false?
Okay, I think I've figured it out. It appears that this is related to a bug in which the PDO MySQL driver emits warnings even when they are supposed to be disabled (See also: this answer). I believe Sentry is then catching these as errors.
I was finally able to replicate, and solve this, by modifying Bill Karwin's test script:
// Initialize the Sentry reporting client
$ravenClient = new \Raven_Client(SENTRY_KEY);
$ravenClient->install();
echo 'Connecting...' . PHP_EOL;
$pdo = new PDO("mysql:host=$host;dbname=$dbname;charset=utf8mb4", $username, $password);
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
echo 'Connected. Waiting...' . PHP_EOL;
sleep(20); // during this sleep, I stop my MySQL Server instance.
echo 'Querying...' . PHP_EOL;
try {
$result = $pdo->query("SELECT 1");
}
catch(\PDOException $e) {
echo 'Caught PDOException ' . $e->getMessage() . PHP_EOL;
}
This will print the following:
Connecting...
Connected. Waiting...
Querying...
PHP Warning: PDO::query(): MySQL server has gone away in /home/xxx/src/test.php on line 37
PHP Stack trace:
PHP 1. {main}() /home/xxx/src/test.php:0
PHP 2. PDO->query() /home/xxx/src/test.php:37
Caught PDOException SQLSTATE[HY000]: General error: 2006 MySQL server has gone away
Done.
And Sentry will record an ErrorException on the query() line.
I was able to solve this issue by implementing the "solution" posted by jferrer on the PHP bug report.
// Convert NOTICE, WARNING, ... in Exceptions
$convertErrorToException = function ($level, $message, $file, $line){
throw new ErrorException($message, 0, $level, $file, $line);
};
// The $previousErrorHandler will contain Sentry's handler
$previousErrorHandler = set_error_handler($convertErrorToException);
try {
$result = $pdo->query("SELECT 1");
}
catch(\PDOException $e) {
echo 'Caught PDOException ' . $e->getMessage() . PHP_EOL;
}
catch(\ErrorException $e) {
echo 'Caught ErrorException ' . $e->getMessage() . PHP_EOL;
}
// Restore Sentry as the default handler
set_error_handler($previousErrorHandler);
This results in just the ErrorException being thrown and caught:
Connecting...
Connected. Waiting...
Querying...
Caught ErrorException PDO::query(): MySQL server has gone away
Done.
I want to check if accessing mysql is possible or not.
I don't wont to have an error message, only true/false if the connection is ready or not.
I tried to do it with this :
$appDB = new mysqli($data[0]['MYSQL']['HOST'], $data[0]['MYSQL']['BENUTZER'], $data[0]['MYSQL']['PW'], $data[0]['MYSQL']['TABELLE']);
if ($appDB->connect_error)
{ $res['code']=FALSE; }
else
{
$appDB -> close();
$res['code']=TRUE;
}
But always a error message will come up - how can i prevent this message from showing ?
"<b>Fatal error</b>: Uncaught exception 'mysqli_sql_exception' with message 'Access denied for user ''
#'localhost' (using password: NO)' in /is/htdocs/...mypath
.php:33
Stack trace:
#0 /is/htdocs...mypath.myfile.php(33): mysqli->mysqli('', ''
, '', '')
#1 {main}
thrown in <b>/is/htdocs/wp1076647_373QG1K1B0/butobo/module/4/code/cms_checkcon.php</b> on line <b>33
</b><br />"
You need to "catch" this fatal exception via a try/catch statement. This allows you to handle the fatal error and then instead of your script crashing due to it, you can output an error message and exit instead :D
PHP Exceptions: http://php.net/manual/en/language.exceptions.php
I hope this helps.
try
{
$appDB = new mysqli($data[0]['MYSQL']['HOST'], $data[0]['MYSQL']['BENUTZER'], $data[0]['MYSQL']['PW'], $data[0]['MYSQL']['TABELLE']);
if ($appDB->connect_error)
{ $res['code']=FALSE; }
else
{
$appDB -> close();
$res['code']=TRUE;
}
}
catch (Exception $e)
{
echo 'Caught exception: ', $e->getMessage(), "\n";
exit;
}
This will change the ERROR to a WARNING, which will not break your script. From there, if you want to hide everything EXCEPT fatal errors, you can use this line of PHP:
error_reporting(E_ERROR);
Error message would display because your PHP is configured to do so. To make it not display, simply configure it like
ini_set('display_errors', "0");
However, this code also stops the execution. It order to prevent it, you have to catch the exception. So it should be like
try {
$appDB = new mysqli($data[0]['MYSQL']['HOST'], $data[0]['MYSQL']['BENUTZER'], $data[0]['MYSQL']['PW'], $data[0]['MYSQL']['TABELLE']);
$res['code']=TRUE;
}
catch (Exception $e)
{
error_log($e);
$res['code']=FALSE;
}
while setting error_reporting(E_ERROR); is rather stupid as it will prevent you from seeing all other errors
When i try to run php code using Parse.com PHP SDK it
the error is "Account already exists for this username"
but it throw all this error message:
Fatal error: Uncaught exception 'Parse\ParseException' with message 'Account already exists for this username' in /Users/yousef/Desktop/project/vendor/parse/php-sdk/src/Parse/ParseClient.php:357 Stack trace: #0 /Users/yousef/Desktop/project/vendor/parse/php-sdk/src/Parse/ParseObject.php(1038): Parse\ParseClient::_request('POST', 'classes/_User', NULL, '{"username":"my...', false) #1 /Users/yousef/Desktop/project/vendor/parse/php-sdk/src/Parse/ParseObject.php(947): Parse\ParseObject::deepSave(Object(Parse\ParseUser), false) #2 /Users/yousef/Desktop/project/vendor/parse/php-sdk/src/Parse/ParseUser.php(108): Parse\ParseObject->save() #3 /Users/yousef/Desktop/project/test.php(20): Parse\ParseUser->signUp() #4 {main} thrown in /Users/yousef/Desktop/project/vendor/parse/php-sdk/src/Parse/ParseClient.php on line 357
The Code i Use
<?php
require 'vendor/autoload.php';
use Parse\ParseClient;
ParseClient::initialize('YousefId', '', 'YousefMaster');
ParseClient::setServerURL('server-ip:1337/parse');
use Parse\ParseUser;
$user = new ParseUser();
$user->set("username", "my name");
$user->set("password", "my pass");
$user->set("email", "email#example.com");
$user->set("phone", "415-392-0202");
try {
$user->signUp();
} catch (ParseException $error) {
echo $error->getCode();
echo $error->getMessage();
}
?>
so how do i just show the error code and message instead of showing all this error.
You need to refer to the ParseException within the Parse namespace.
Try
catch (Parse\ParseException $error) {
// ...
}
who can help me i have this error when i want go to the file article.php:
Fatal error: Uncaught exception 'MongoException' with message 'Invalid object ID' in /Applications/XAMPP/xamppfiles/htdocs/www/Site/Test/article1.php:14 Stack trace: #0 /Applications/XAMPP/xamppfiles/htdocs/www/Site/Test/article1.php(14): MongoId->__construct('Notice...') #1 {main} thrown in
beginning of the file article1.php
<?php
$id = $_GET['id'];
try {
$connection = new MongoClient();
$database = $connection->selectDB('test');
$collection = $database->selectCollection('articles');
} catch(MongoConnectionException $e) {
die("Failed to connect to database ".$e->getMessage());
}
$article = $collection->findOne(array('_id' => new MongoId($id)));
?>
You are only catching an exception of the type "MongoConnectionException" while the code is throwing a more generic "MongoException"
Catch(MongoException $e)
I have a Database class:
<?php
namespace Database\MySQL;
class Database
{
function __construct(){
mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
try {
$this->Connection = new mysqli(
"", // Testing with no host
"", // Testing with no user
"", // ... no password
"" // and no DB name
);
}
catch (mysqli_sql_exception $e) {
throw $e;
}
...
?>
But instead of a getting an exception, I get a Fatal error: Fatal error: Uncaught exception 'mysqli_sql_exception' with message 'No database selected' in Database.php.
I have tried the same thing with a simple query:
try {
$this->Connection->query("SET NAMES 'utf87'"); //utf87 just for test
}
catch (mysqli_sql_exception $e) {
throw $e;
}
And I still get Fatal error: Uncaught exception.
Your problem is that you are catching the exception, but then just throwing it again without catching it.
If you replace throw $e; with echo "Caught the exception";, you will see that your script is catching the exception. But because you throw it again, it will result in an error unless you have a higher-level try/catch block or a global exception handler.
Also, as many have pointed out in the comments, you need to be careful of namespaces. You need to use a use statement or refer to \mysqli_sql_exception.