mysqli or die, does it have to die?
Does it have to die
Quite contrary, it shouldn't or die()
ever.
PHP is a language of bad heredity. Very bad heredity. And or die()
with error message is one of the worst rudiments:
- die throws the error message out, revealing some system internals to the potential attacker
- such error message confuses casual users, because they don't understand what does it mean
- Besides,
die
kills the script in the middle, leaving users without familiar interface to work with, so they'd likely just drop out - it kills the script irrecoverably. While exceptions can be caught and gracefully handled
die()
gives you no hint of where the error has been occurred. And in a relatively big application it will be quite a pain to find.
So, never use die()
with MySQL errors, even for the temporary debugging: there are better ways.
Instead of manually checking for the error, just configure mysqli to throw exceptions on error, by adding the following line to your connection code
mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
and after that just write every mysqli command as is, without any or die
or anything else:
$result = mysqli_query($link, $sql);
This code will throw an exception in case of error and thus you will always be informed of every problem without a single line of extra code.
A more detailed explanation on how to make your error reporting production ready, uniform and overall sensible while making your code much cleaner, you can find in my article on PHP error reporting.
Is mysqli_query() or die(mysqli_error()) a good practice?
This practice is just awful. It's a bad heredity from the last century ways of writing code.
Instead, you have to add this line before connection code
mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
it will relieve you from the need of writing extra code for the every mysql call, as it will make mysqli to throw an Exception
in case of error automatically.
While exception itself is way better than regular error, as it can be caught and gracefully handled. Yet it will be converted into error, if not caught, which is again all right - because regular errors, depends on the site-wide settings, can be either shown on-screen or logged. Again without the need of writing a single line of extra code.
While developing, just have display_errors
setting on
and you will see all the errors the moment they occurred.
While on a live site, display_errors
have to be turned off
, but log_errors
have to be on
instead - and it will make your exception logged, for your future reference.
A form doesn't submit
Just simply add or die(mysqli_error($db));
at the end of your query, this will print the mysqli error.
mysqli_query($db,"INSERT INTO stockdetails (`itemdescription`,`itemnumber`,`sellerid`,`purchasedate`,`otherinfo`,`numberofitems`,`isitdelivered`,`price`) VALUES ('$itemdescription','$itemnumber','$sellerid','$purchasedate','$otherinfo','$numberofitems','$numberofitemsused','$isitdelivered','$price')") or die(mysqli_error($db));
As a side note I'd say you are at risk of mysql injection
, check here How can I prevent SQL injection in PHP?. You should really use prepared statements to avoid any risk.
mysqli_error() Can't make the conversion
From the mysqli documentation the syntax is
Object oriented style
string $mysqli->error;
Procedural style
string mysqli_error ( mysqli $link )
So depending on your programming style you have either something like$mysqliObj = new mysqli( ... );
or $link = mysqli_connect( ... )
in your code. Depending on this you have to use either
$mysqsliobj->error
or
mysqli_error($link)
Just a few comments on this:
- You should not use this in production. If there is an error in your Query or the Database is offline you don't want to print the whole query to the user. Maybe this query is containing something that should not be public.
- You also don't want to stop the execution at this exact point. Just catch the error, write it into a log file and show a useful error message to the user.
Proper mysqli_query and mysqli_error configuration
There are two errors in the code above:
- You missed to declare
$link
global
as$mysql_hostname
etc. - You passed the wrong argument type to
mysqli_error()
it expectsmysqli
and you passed astring
I have changed your example:
<?php
include('mysql_config.php');
// declaring an additional global var.
$link = NULL;
function mysqlConnect()
{
global $link; // using the global $link
global $mysql_hostname, $mysql_username, $mysql_password, $mysql_database;
$link = mysqli_connect($mysql_hostname, $mysql_username, $mysql_password)
or die('Could not connect: ' . mysqli_connect_error());
mysqli_select_db($link,$mysql_database) or die('Could not select database');
return $link;
}
function mysqliClose($link)
{
mysqli_close($link);
}
function sendQuery($query)
{
global $link; // using the global $link
$result = mysqli_query($link, $query) or die('Query failed: '
. mysqli_error($link)); // note $link is the param
return $result;
}
Why die with connect_error() is not working?
You need to decide whether you use procedular or object oriented version of mysqli.
However, still you can change your if condtion to:
if (!$this->con) {
die(mysqli_connect_error());
}
it should work. You can also see the example on manual
mysqli doesn't return instance with die()
The [..] or die()
construct leads to funny behaviour in conjunction with the return statement: The whole thing is interpreted as a boolean expression.
And because new mysqli
will never be false, the "die" is never processed, and thus, your function returns true
instead of a newly created instance of mysqli
.
If you still would like to use or die()
, do this:
$result = new mysqli($host, $user, $pwd, $db) ;
if (!$result) die ("Can't open database.");
return $result;
Does mysqli::reap_async_query() have side effects?
Is there a reason for it [
mysqli::reap_async_query()
] to be here, does calling it even without reading its return value has any important side effect ?
The return value is not assigned to a local variable, however it is still returned.
So the original interest was in calling that function. And for what for, has been written about in the commit message.
According to the Git history, the call to @$GLOBALS['con']->reap_async_query(); was added to support async SQL queries.
Let's consider this example:
$con->query('SELECT SLEEP(5) as `zzzZZZ...Schnarch...Schmatz..zzz`', MYSQLI_ASYNC);
$con->reap_async_query();
How long does it take to execute this code?
This is the reason how that call supports async queries. If an async query would still run on the connection (it has not been reaped yet), every new query would fail.
So add of the call in-so-far supports async SQL queries as it allows to fire one on the same (shared) connection that might be in use for other queries, too.
Additionally you ask:
Also, why is it triggering this error ? I understand that trying to read a result before any query has been executed could trigger an error but the error indicates that the connection is not active, which does not seem to be the case.
Let's take a look at the error, actually a message on the diagnostic channel:
PHP Warning: mysqli::reap_async_query(): Connection not opened, clear or has been closed in ...
As we know the connection has been opened and has not been closed, the last point might be it:
[...] Connection [...] clear [...]
Now I have not programmed that error message, but my reading of it is that there is no async query running yet on the (open) connection - the connection is clear.
It produces a warning as this might not be intended (there is no need to reap a clear connection normally) and henceforth as with your function this is intended, the call is prefixed with the error suppression operator (@
).
Related Topics
How to Create Multi Level Category Hierarchy ( Category Tree ) - Codeigniter
How to Pass an Array Within a Query String
How to Prevent a User from Directly Accessing My HTML Page by Writing Url
Sending Post Requests Without Waiting for Response
Validating Base64 Encoded Images
How to Get Only Date from Datetime in Codeigniter
How to Check, If a PHP String Contains Only English Letters and Digits
Regex Optionally Match a Pattern Multiple Times
Api to Get All the Reviews and Rating from Google for Business
What Is the Easiest Way to Check If Time Is Set in Datetime Variable
Laravel: Products,Categories and Subcategories! (Relation Ships)
Remove License Check from Script Code in Codeigniter
Laravel Save() Method Returning True But Not Updating Records
Display Text(Html) Saved in Database Using Ckeditor
Warning: Mysqli_Connect(): (Hy000/1049): Unknown Database in MAC Terminal Only