Reputation: 128
I am trying to connect to the database, and when I try with everything correct, the database connects, and everything is fine. But, when I try to connect using some wrong credentials, it throws an error message, and I am figuring out a way to hide the error message from the user.
function connectDatabase(){
$dbServerName = 'local_host';
$dbUsername = 'root';
$dbPassword = '';
$dbName = 'kishor_me';
$conn = mysqli_connect($dbServerName, $dbUsername, $dbPassword, $dbName);
if (!$conn) {
echo "error message";
}else{
echo "success message";
}
}
Isn't there any way I can show the user the critical error message and not the other error description generated by the language and also not give an HTTP 500 error?
Upvotes: 3
Views: 1309
Reputation: 157892
It doesn't show your custom error message because starting from PHP 8.1, mysqli now throws an exception on error, instead of asking a programmer to handle it manually.
What is more important, there must be no such custom error message in your code.
It seems you are using some outdated tutorial, that offers incorrect approach at reporting errors: a code that tries to detect the connection error manually and outputs something on its own. But your code shouldn't be doing anything like that: both PDO and mysqli can raise errors automatically and, moreover, such a part of your code should almost never talk to the user on its own.
Now let's answer your questions step by step:
In the ancient times, some 10 years ago, PHP used mysql extension to talk to MySQL database, which was unable to handle errors automatically, and every database operation had to be checked for errors manually. That's where this if (!$conn)
stuff comes from. But this extension is long gone, and PHP got a new one, mysqli. Which has the ability to raise errors automatically, just like any other command in PHP, require
or header()
for example. You aren't checking every require
or header()
result manually, are you? So you shouldn't with mysqli or PDO.
As you can see, mysqli_connect()
(as well as new mysqli()
or new PDO()
) produces the error automatically, just like any other PHP function. So there is just no use for the if (!$conn)
part. Neither on connect, nor with query()
or any other database function.
In a nutshell: you don't need any code to detect database errors. They are regular errors now. And, if you think of it, not only database errors must be hidden. Any other error, like "Headers already sent" or "No such file or directory" must be hidden from a site user as well.
So the problem is more generic now:
To hide error messages from a site user, you must use a configuration option which is intended exactly for that: display errors
. While set to 0
, it will prevent PHP from displaying any error occurred. It's best to be set in the php.ini
but in case you don't have a control over PHP configuration, at least you can set it right in the PHP code:
ini_set('display_errors', 0);
The best part of it, this is just a single place where it's set. Therefore, on your local PC or on a test server you can set it to 1 and watch all errors online. Again, without any changes in the code: as you can see, a failed connection attempt already provided a detailed error message, without that if (!$conn) {
stuff. But on a live server, display errors
must be set to 0, so not a single error message leaks to the user, while log_errors
must be set to 1. That's a simple rule which is, sadly, seldom mentioned in the books or tutorials. By the way, I'd recommend PHP&MySQL book by Jon Duckett, where this approach is explained in detail.
But well, having a system error message hidden, what about a user-friendly error page?
Like it is said above, a site user shouldn't be given any particular details about the error. Which means you can use a single piece of code that would handle all irrecoverable errors for a site user, be it a database, or filesystem, or memory, or whatever else error.
The most convenient solution would be to configure an error handler. Here is one from my article on PHP error reporting:
set_exception_handler(function ($e)
{
error_log($e);
http_response_code(500);
if (ini_get('display_errors')) {
echo $e;
} else {
echo "<h1>500 Internal Server Error</h1>
An internal server error has been occurred.<br>
Please try again later.";
}
});
depends on the display_errors
value, it will either display the error itself, or just a generic message, that you can decorate to your taste.
Note that it "gives an HTTP 500 error" which, contrary to your request, is what actually must be done. When your page cannot provide the actual content due to server error, it must respond with 5xx HTTP code.
Still there are cases when you want to catch the connection error.
For example, if you want to test the credentials provided by the user for the installation script. Then you can wrap the connection in a try..catch. But it should be a distinct connection test code, separate from your regular connection code.
Or in case you have a backup scenario when a connection fails, you can also wrap the connection in a try..catch. In a nutshell, use try..catch if you have a handling scenario other than just report the error, in which case just leave the connection code alone.
Some people are concerned about database password that may appear in the stack trace. Even when credentials are not displayed, it makes some people feel uneasy when sensitive information even gets logged.
Update your PHP version. Starting from 8.2, it hides the database password from the stack trace.
Upvotes: 5