I have some code that allows a user to input details for their database on their server. After they submit the details, the code checks a connection to the database to see if valid details were entered. I want it to give outcomes of variables being true if the connection either works or does, like this:
$mysqli = new mysqli($_POST['dbHost'],$_POST['dbUser'],$_POST['dbPassword'],$_POST['dbName']);
if ($mysqli->connect_errno) { $badDetails = true; }
else { goodDetails = true; }
Problem is, if the details are indeed incorrect, it shows a PHP warning from the first line of the code above giving 'Unknown MySQL server host'.
What is the way around this? I don't want PHP throwing it's own visible error for this, I want to deal with the error myself.
You should not worry about visual errors. In a production environment, these should be turned off in the ini, and all errors should go to a log on the server instead of just to the screen.
This is configured with the display_errors setting and error_reporting()
Many frameworks override the PHP error handler with a custom implementation to display error in a pretty way, depending on their severity.
To achieve this, you can override the PHP error handler
As seen in the manual one can register custom handlers for regular errors and exceptions. And it is also possible to trigger an user defined error.
Just use a die()
$mysqli = new mysqli($_POST['dbHost'],$_POST['dbUser'],$_POST['dbPassword'],$_POST['dbName']) or die("Database Connection Failed");
A quick, dirty method would be error supression:
$con = #mysqli_connect( /* info */ );
Note that you should not keep this there, as this will suppress all errors, and mysqli can have multiple errors that you might need to know about.
Though I would check the host variable first, to see why the error is caused. You can also use die.
$con = mysqli_connect(/* info */) or die ("SQL Error!");
As far as where to look, try seeing that the host var is actually set and check it's value:
if (!isset($_POST['dbHost'])) {
echo "Host var not set!";
} else {
echo "Host var set: " . $_POST['dbHost']
}
Related
in this case I accidentally made a wrong database username or password, my goal here is how to generate an error in the form of JSON data and open in the form of a PHP warning or error like my picture
// Here's my PHP Code
if (!empty($_POST)){
$test_conn = new mysqli('localhost' , $_POST['db_user'] , $_POST['db_pass']);
$conn = new mysqli('localhost' , $_POST['db_user'] , $_POST['db_pass'] , $_POST['db_name']);
if ($test_conn->connect_error){
$response = array('status' => 0 , 'message' => "Failed Connect to Databases");
print_r(json_encode($response));
}else{
// The Code When Username and Password is Correct
}
}
here I know that the username or password is wrong, but I am confused how to only display the json data in the image at the bottom and not display the php warning
If you are sure that this is what you want, just disable errors by adding the following at the top of your script:
error_reporting(0);
if you want to hide errors for a given code, use the following:
// Disable errors and get current error reporting level
$err = error_reporting(0);
/* here goes you buggy code */
// Set the default error reporting level
error_reporting($err);
You have to suppress the php error reporting in order to use your own check of connect_error. The php documentation on mysqli::$connect_error suggests to do this with the # error control operator like this:
$test_conn = #new mysqli( ... )
This will only suppress errors caused by a faulty instantiation of the mysqli object. It should be clear that you then have to handle these errors yourself (as you already do). All other errors still could cause your php script to stop and not to return any JSON string to the AJAX function that called the script.
As #Victor correctly pointed out in his answer you could disable all errors for the script (or parts of it) by setting error_reporting(0) at the beginning at the script. In that case you wouldn't have to check other possible errors, e.g. if the db credentials in the $_POST array are not set or empty.
As #Ben mentioned in his comments you could also make mysqli throw exceptions to avoid fatal errors by setting mysqli_report(MYSQLI_REPORT_STRICT). This would also be a feasible solution for your problem.
As a general consideration you should make these settings in your php.ini:
display_errors = Off
error_log = syslog
This prevents error message from being exposed to the www (security) while making them available for developers in /var/log/syslog (maintainability).
i hope someone can help me, ive been struggling on this for 3 days now.
here is my situation, i am making a website with php, and i have 2 computers as servers with wampserver...
main server is 192.168.0.10
secondary server is 192.168.0.12
and a virtual machine where im trying out if the remote conection works
my website is hosted on my main server so the conexion query is...
$conexion = mysqli_connect("localhost","root","","dbdaq");
it works fine, i even have master to master replication on the servers.
but what i need to do is that when main server is down it needs to try to conect to the database on the seondary database, so im trying to use the code...
$conexion = mysqli_connect("localhost","root","","dbdaq");
if (!$conexion){
$conexion = mysqli_connect("192.168.0.12","root","password","dbdaq");
}
but when i manually turn of the mysql services on main server it doesnt actually try to use the other servers database...
it keeps giving me the error that says
Warning: mysqli_connect(): (HY000/2002): No connection could be made because the target machine actively refused it. in C:\wamp64\www\PaginaV2\Pagina\PHP y JS\Procesoalumno.php on line 2
Using # to suppress error messages is a bad idea, and a bad practice. A better solution is to set mysqli to throw exceptions on failure, and catch the exception.
You can set mysqli to throw exceptions by adding the following line before you make your connection(s).
mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
Using exceptions over suppressing the error, you can extract the relevant error-message and error-code if you need them for specific handling or logging, in a much cleaner way than you can with suppressing the errors.
Though it might look like its more complex, the reason for this is that we also test the second connection (which you should do anyways, regardless how you do it) - and we test the second connection the same way we test the first connection, by a second try/catch inside the first catch block.
mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT); // errors in MySQLi now throws exceptions
try {
$conexion = mysqli_connect("localhost","root","","dbdaq");
} catch (Exception $e) {
try {
$conexion = mysqli_connect("192.168.0.12","root","password","dbdaq");
} catch (Exception $e) {
echo "Connecting to both databases failed";
exit;
}
}
Try this: use php's # operator (the error control operator) to suppress the error message from the first connection failure. Try this.
$conexion = #mysqli_connect("localhost","root","","dbdaq");
if ( !$conexion ) {
$conexion = mysqli_connect("192.168.0.12","root","password","dbdaq");
}
It seems likely your code for the failover connection works correctly, but you still get an obnoxious error message. The # operator suppresses the message.
How would I go about getting PDO statements to generate a safe error message? I don't want the user to see the error message. I want them to get directed to a page that says a clean message, "Whoops something unexpected happened!". I would also like to log the errors in a database to review and catch errors others are generating.
I'm using PHP and MySQL.
I found that when you make your connection you can set your error handling like this.
$dbh = new PDO($dsn, $user, $password);
$dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
Anyone do anything like this before?
So this is just a suggestion as I have never tried this but after thinking about it a bit I think it would be an interesting option to explore. As I am fairly new to PHP & PDO I'm sure there are other and better ways.
Perhaps you could try using the try function of PHP and then instead of echo'ing (if failed) the PDOException you could run another function that prints it to a text file. Something like.
<?php
try {
$dbh = new PDO('mysql:host=localhost;dbname=test', $user, $pass);
foreach($dbh->query('SELECT * from FOO') as $row) {
print_r($row);
}
$dbh = null;
} catch (PDOException $e) {
$strFileName = 'whatever.txt';
if(!is_writable($strFileName))
die('Change permisions to ' . $strFileName);
$handle = fopen($strFileName, 'a+');
fwrite($handle, "\r" . $e->getMessage() . "\r");
fclose($handle);
}
?>
This way you would avoid a DB connection (which is the problem I guess) but still save the error.
You would perhaps want to omit the echo'd text after die within the if statement.
I think it is better to write your logs to a file, instead of a database. Especially since you want to log PDO errors, which indicate something is wrong with your database connection.
You can show the user a nice error page by catching your errors. You can redirect your users to your error page then, in case something went wrong.
You have to understand that PDO do not generate a "safe" or "unsafe" error message. It does generate an error message. That's all. The rest is is the responsibility of site-wide PHP settings.
PDO is not the only source of errors. Why care of PDO errors only? Why not to handle ALL errors the same way?
Want errors logged? It's a matter of one PHP ini setting.
Want errors not to be displayed? It's a matter of one PHP ini setting.
Want generic error page to be shown? It's a matter of simple function that will handle all errors at once.
Everything can be done proper and straight way, without wrapping every statement into try catch. Without writing into log manually. Without even single additional line of code.
You need to set up PHP error handling, not PDO.
And of course, it makes absolutely no sense in trying to store a database error in the same database that failed you right now. Errors have to go into error log on a live server and on screen - on a local development PC.
Anyone do anything like this before?
Sure. Every single one of 1000000s sites in the world. The way described above.
I'm fairly new to PDO. I have a try and catch which catches and displays errors when something doesnt exist i.e a table.
However, how can i show the error message/cause for sql failed commands.
For example below i was trying to insert the word "enabled" into a tiny int column - however, only showed me a blank screen - had to debug myself. How can i show SQL failed error messages?
$db = new PDO('mysql:host='.$dateBaseHost.';dbname='.$dateBaseName, $dateBaseUsername, $dateBasePassword);
$db->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
// set/get variables
$id = (isset($_GET['id']) === true) ? $_GET['id'] : die("ID not set") ; // ? : shorthand if else
$action = (isset($_GET['action']) === true) ? $_GET['action'] : die("Action not set") ; // ? : shorthand if else
// query
$query = $db->prepare(" UPDATE `telephoneCountries` SET `enabled`= :action WHERE `id` = :id ");
// bind parameters - avoids SQL injection
$query->bindValue(':id', $id);
$query->bindValue(':action', $action);
// try... if not catch exception
try {
// run the query
$query->execute();
}
catch (PDOException $e){
//sendErrorMail($e->getMessage(), $e->getFile(), $e->getLine());
echo $e->getMessage();
echo $e->getFile();
echo $e->getLine();
}
i was trying to insert the word "enabled" into a tiny int column
it's fairly OK to mysql. 0 will be inserted.
how can i show the error message/cause for sql failed commands.
for the real errors you have to just setup PHP to display them
ini_set('display_errors',1);
so - you'll be able to see every uncaught exception.
Also, if you are only going to display an error message, but not handle the error itself, just don't use try..catch at all. PHP will do all the job already. That's the point.
Most people do confuse error reporting with error handling. The latter shouldn't be used for the former. When dealing with error messages, your only goal is to make PHP to raise them, and to set up the proper destination:
on a development server an error message have to be show on-screen
on a live sever it shouldn't be shown, but logged instead.
without all these try-catch blocks you'll be able to control error messages (including non-exceptions) by means of a couple ini settings or single error handler function (which I mentioned to you in the other answer).
use try..catch only if you are going to handle the error itself - say, to connect to another server for example.
So, to answer your question more verbosely:
Set PDO in exception mode. Done already.
Remove all try..catch blocks that deals with error messages only.
Setup PHP to show errors on a development server using ini directive above.
On a live server it is strongly recommended to log errors instead of emailing them. But if you still want it this way - use single custom exception handler function to send emails instead of hundreds try..catch blocks
What is the "proper" way to deal with errors when manipulating a sql database with php?
What Im currently doing looks like this:
$connection = new mysqli('hostname', 'user', 'pass', 'database');
if ($connection->connect_errno) {
reportError("DB_CONNECTION_ERROR", $connection->connect_errno, $connection->connect_error);
displayError("DB_CONNECTION_ERROR");
}
$stmt = $connection->stmt_init();
$q = "query";
$stmt->prepare($q);
$stmt->bind_param('s', $username);
$stmt->execute();
reportError() is part of an error handling file I wrote and logs the error in a database
displayError() is part of the same file and tells the page what to display (as opposed to displaying the actual error).
However Im not sure of how to check for other errors, such as whether a statement was successfully prepared or whether a query was successful. Any recommendations appreciated!
Don't you find it quite odd to write database connection errors... into database?
I see also no point in having custom displayError() function. It should be generic _503() function, sending corresponding header along with general excuses.
I see no point in having custom logError() function either. PHP quite capable to log errors itself. trigger_error() serves me best.
Im not sure of how to check for other errors, such as whether a statement was successfully prepared
Ah, this one. Exceptions.
Mysqli should throw an exception if something went wrong. See mysqli_sql_exception for more details.
In your client code, you can then wrap your code in try/catch blocks:
try {
} catch (Exception $e) {
}
Sometimes, there are exceptions that can't be solved within a try/catch block, for example, the database server is down, and a site that is heavily reliant on the database would not be able to function anyway.
For those very critical problems, you can allow the exception to bubble upwards. You should then set an exception handler at the beginning of your script to catch those exceptions, notify the administrator and do some logging, then display an 500 error page to the user.