Which method I should use and why? - php

I am establishing a database connection in php using the function
$DBConn = mysql_connect ("localhost" , "testuser" , "test123")
At the time of releasing the connection I am using
if( is_resource($DBConn) )
to check whether the connection is currently set or not. I want to know is it efficient to do this or I should check the connection like this
if( $DBConn )
I want to know prod and cons of using both the statements.

First of all, you should no longer be using mysql_xxx functions; there are many articles out there that discuss the benefits of having prepared statements, etc. with PDO / mysqli.
By looking at the manual, it states that it returns a link identifier or false on failure. You shouldn't make assumptions as to what exactly this identifier is, it's usually a resource but it may as well be an object or integer. I would simply negate the easier condition:
if (false !== $DBConn) {
// do something with the database
}
Or, alternatively:
if (false === $DBConn) {
throw new Exception("Could not connect to database");
}
// do something with the database
Edit
Using if ($DBConn) { ... } is okay as well, because it's basically the opposite of 0, false, null, "" and empty array.

Both of them are essentially the same, though one might argue that called the is_resource method has the overhead of calling the function, the if also has to determine this and it virtually leaves no difference between both of them. Its all about your style of coding and readability i guess

A resource identifier is returned upon successful connection or querying. Thus the function is_resource will identify a variable as a resource or false.
and if an If expression evaluates to TRUE, PHP will execute statement, and if it evaluates to FALSE, it won't.

Related

PHP PDO in Exception Mode - Still need to check return of execute function (and others)?

TLDR: Does anyone know of specific cases, besides the one shown below, where PDO::exec(), PDO::query(), PDO::prepare(), or PDOStatement::execute() can return false without an exception being thrown, despite PDO::ATTR_ERRMODE being set to PDO::ERRMODE_EXCEPTION?
I'm trying to decide if I want to add a check for false to every database query I write going forward, or if that is redundant.
Edit: I currently use MySQL exclusively, but if portability is a factor, that might be enough to base the decision on. I use PDO::ATTR_EMULATE_PREPARES => FALSE if that matters.
This is the specific case I mentioned. If you prepare a statement with 0 or more placeholders (of either type) and then supply an array of arguments to PDOStatement::execute() with more elements than there are placeholders, false is returned without an exception being thrown. Note that the execution succeeds (and only the extra binding fails) if PDOStatement::bindValue() is used instead. Using fewer parameters than placeholders does throw an exception, whether the parameters were supplied to the execute function via an array or bound using PDOStatement::bindValue()/PDOStatement::bindParam().
// Execute returns false, no exception thrown
$so = $rh->pdo->prepare("SELECT * FROM config");
if($so->execute(['Test']) === FALSE) echo '1. False returned <br />';
// Execute does not return false, no exception thrown
$so = $rh->pdo->prepare("SELECT * FROM config");
if($so->bindValue(1, 'Test') === FALSE) echo '2. Binding failed <br />';
if($so->execute() === FALSE) echo '2. False not returned <br />';
// Execute returns false, no exception thrown
$so = $rh->pdo->prepare("SELECT * FROM config WHERE webmaster_name = ?");
if($so->execute(['Test', 'Wee']) === FALSE) echo '3. False returned <br />';
// Execute does not return false, no exception thrown
$so = $rh->pdo->prepare("SELECT * FROM config WHERE webmaster_name = ?");
$so->bindValue(1, 'Test');
if($so->bindValue(2, 'Wee') === FALSE) echo '4. Binding failed <br />';
if($so->execute() === FALSE) echo '4. False not returned <br />';
Outputs:
1. False returned
2. Binding failed
3. False returned
4. Binding failed
On a select statement, it isn't particularly dangerous in this case to rely on exceptions, as an error would occur anyway if you tried to call a fetch method on FALSE instead of a PDOStatement object. But there are queries like INSERTS or UPDATES that could silently fail on you if you don't do the false check.
I have been learning PDO and I am trying to decide on general practice for error handling going forward.
I definitely prefer exceptions, as I already have a good site wide handler that can be configured for different scenarios. And it seems using exceptions will mean less typing, since you don't have to check the returns of many PDO functions explicitly.
OR DO YOU? (cue dramatic music)
When I was reading up, I came across more than one mention of PDO functions (not the fetching variety) returning false without an exception being thrown.
My question is whether or not it is considered best practice to also check the return of those functions, or if most people consider that overkill.
I have seen a lot of conflicting statements on SO. I have seen numerous statements on one side: "PDO exceptions are reliable"; "PDO exceptions will always be thrown when FALSE would have been returned" (upvoted by people saying "I think is true").
These are some comments that are leading me to wonder, though I have yet to see a specific example besides the one I mentioned.
From Can PDO methods fail and not throw PDOException?:
I could not seem to replicate this scenario from a few test cases (I have emulation mode off).
"(Ryan Vincent) when emulates is false and ... binding types are incorrect. It may not throw an exception sometimes."
This one seems to have been disproved? I'm not sure how to test this.
"(Xorifelse) Now for committing to fail, I believe there is 1 scenario that would cause it to return false without throwing an exception and that is when the connection to the server drops after connecting to the database and before calling PDO::commit, quite good to know if you have a remote database server. So to answer your question, yes it can fail without throwing an exception, but its timing has to be very specific even more so if you have a local database."
From will a false returned PDO execute() the same as the exception it thrown?:
This is the only specific scenario I have come across that I have been able to duplicate (see above).
"(Niksac) I have seen execute() returning false without throwing an exception which is kind of unexpected / bad behaviour in my opinion. This means that we basically have to do both - error and exception handling in parallel. In my case: if I prepared an insert query without any parameters and then executed with a parameter. Execute will not throw an exception but return false."
From Should I check the return value of an execute operation in pdo php:
"(castis) $stmt->execute() can absolutely return false without throwing an exception."
I think I found at least one other non-specific mention of it being possible (false returned, no exception), though I can't track them down again.
Looking through PDO tutorials online, most of them don't check the returns whenever exception mode is used. But I did come across a couple people recommending it.
The case I described is not something I am likely to screw up in everyday use. Or if I do screw it up, I should find out immediately. And if I ever dynamically built the number of placeholders or parameters in the query, I would know to make sure the count matches and/or check for false in this one case.
I just don't want to check the return of every use of execute, query, etc. if it isn't really necessary. If the example I mentioned is the only known case, I would feel comfortable leaving the false check out of most queries, which would allow me to do more method chaining:
$user_info = $rh->pdo->query("SELECT * FROM users WHERE user_id = 1")->fetch();
// vs
$so = $rh->pdo->query("SELECT * FROM users WHERE user_id = 1");
if($so === FALSE) // Throw an exception
$user_info = $so->fetch();
I guess what I'm looking for is some reassurance from more experienced developers that it's okay to bypass this check as I'm seeing people do. Either that, or people telling me how they have been burned by bypassing that check.
There are definitely different gotchas depending on which database you are using. If portability is a concern, I'd not rely on some of what might be MySQL idiosyncrasies that you seem to be finding, above.
For example, there are these:
PHP PDO Postgres versus Sqlite column type for count(*)
PHP Postgres PDO driver does not support prepared statement?

PHP !is_resource($RS) vs ($RS === false) vs !$RS

When checking for a valid resource in PHP, I'm wondering if these are interchangeable. The first two methods are being used where I work and as far as I can tell they are accomplishing the same thing.
Edit: When I first asked this question I was using some code copied from the PHP manual for my example, which contained mysql commands. Since I'm not using mysql I decided it would be better to rewrite the question.
Method 1 - use !is_resource, which has a little more overhead than a direct comparison such as in method 2
$RS = sqlsrv_query($con, $SQL);
if (!is_resource($RS)) {
die('not a resource');
}
Method 2 - a direct comparison
$RS = sqlsrv_query($con, $SQL);
if ($RS === false) {
die('not a resource');
}
Method 3 - is this the same as method 2, just less wordy? Or is there some nuance with the === that I'm missing?
$RS = sqlsrv_query($con, $SQL);
if (!$RS) {
die('not a resource');
}
Thanks
mysql_connect will only return either a resource, or false.
Effectively, !$db_link and $db_link === false are the same. Edit: "in this instance." They aren't actually the same, as === performs strict type checking, but for the purposes of this discussion, they are effectively the same.
is_resource is effectively the same as well, just slightly more overhead but not enough to be concerned for such a micro-optimization.
You should not be writing new code using mysql_ functions. It has been deprecated for a very long time. The replacement was mysqli_.
If you know what possible values you're dealing with, and these values can clearly be distinguished by a simple boolean test, then that is perfectly fine enough. mysql_connect returns either a resource or a boolean false. The boolean false will always be falsey and the resource will always be truthy, hence if (!$db_link) is a perfectly adequate and concise test. There is no case in which this would fail given the two possible values that $db_link can be here.
=== false is more explicit about the boolean comparison, but unnecessarily so. It doesn't add anything, except verbosity.
is_resource also works for your purpose and is more explicit the other way, but again unnecessarily so. It won't match any additional case a simple boolean comparison wouldn't here.

What does "or" do in the context of errors?

Reading this question I want to copy #Your Common Sense's error checking when using mysqli
$query="INSERT INTO testtable VALUES (23,44,56)";
$stmt_test->prepare($query);
$stmt_test->execute() or trigger_error($stmt_test->error);
$stmt_test->close();
How does or work? Another example of it's use is
$fh = fopen($myFile, 'w') or die("can't open file");
How is it different than using an if statment and would should it be used instead?
If the first statement returns false, then the second one is executed. That's it.
This is often how boolean "or" expressions are evaluated in programming languages. If you have a statement involving functions thus:
if (a() or b()) { ... }
then PHP works out that, if a() returns true, there is no need to evaluate the second function, since the overall result will be true regardless of the outcome of the second part. We can use this trick as a simple if mechanism:
(operation_that_might_fail() or report_error());
Here, I've removed the if around the clause. This will be evaluated just as before - except the result of ORing the two is then thrown away, since we don't need to do anything with it.
For this to work, operation_that_might_fail() must return boolean true on success, and false otherwise. As it happens, many PHP functions do exactly that, so we can often use this approach.
Side note: whilst the statement or is arguably clearer, PHP programmers tend to prefer the operator ||. Similarly, and will do what it says, but && is more common.

PHP generating a phantom warning for code that is not executed

In an effort to tidy up my code, I've encapsulated my database reads into its own function, which accepts a SQL command for the argument, as well as an optional $getArray argument which specifies whether I am returning an array as the result (true for SELECT, false for UPDATE, etc).
function readDB($sql, $getArray = false)
{
$conn = odbc_connect('myAccessDataBase', '', '');
if (!$conn)
return exit('Connection Failed: '.$conn);
if ($getArray = false)
odbc_exec($conn, $sql);
else
{
$res = odbc_exec($conn, $sql);
if (!$res)
return exit('Error in SQL');
return odbc_fetch_array($res);
}
odbc_close($conn);
}
The code above works as expected except for one small caveat. If I am performing an UPDATE vs a SELECT, I get a warning due to $getArray being set to false:
Warning: odbc_fetch_array() [function.odbc-fetch-array]: No tuples available at this result index in C:...\functions.php on line 14
I understand the warning, which makes sense if that line were to actually be executed, however it is not. My question is in regards as to why PHP is evaluating the contents of the else portion of my if statement, which is not even being hit during runtime. I understand that the UPDATE cannot return an array, hence why I am evaluating $getArray to determine whether I expect such a return. What can I do to circumvent this warning? Regardless, I am still pretty fresh with my PHP, and am probably going about this the wrong way anyhow. Cheers!
You're setting the variable TO FALSE instead of evaluating it FOR FALSE If you change this line:
if ($getArray = false)
to
if ($getArray == false)
It should work.
edit
On another note, you should do your test in reverse. Instead of testing for false, test for true and THEN have an else. It makes a little more sense logically for anyone coming in to look at your code later.
Instead of If this IS NOT the case then do this it makes more sense to say if this is the case, do this
So switch your code blocks around and test:
if ($getArray)
The line
if ($getArray = false)
must be
if ($getArray == false)

How does "do something OR DIE()" work in PHP?

I'm writing a php app to access a MySQL database, and on a tutorial, it says something of the form
mysql_connect($host, $user, $pass) or die("could not connect");
How does PHP know that the function failed so that it runs the die part? I guess I'm asking how the "or" part of it works. I don't think I've seen it before.
If the first statement returns true, then the entire statement must be true therefore the second part is never executed.
For example:
$x = 5;
true or $x++;
echo $x; // 5
false or $x++;
echo $x; // 6
Therefore, if your query is unsuccessful, it will evaluate the die() statement and end the script.
PHP's or works like C's || (which incidentally is also supported by PHP - or just looks nicer and has different operator precedence - see this page).
It's known as a short-circuit operator because it will skip any evaluations once it has enough information to decide the final value.
In your example, if mysql_connect() returns TRUE, then PHP already knows that the whole statement will evaluate to TRUE no matter what die() evalutes to, and hence die() isn't evaluated.
If mysql_connect() returns FALSE, PHP doesn't know whether the whole statement will evaluate to TRUE or FALSE so it goes on and tries to evalute die() - ending the script in the process.
It's just a nice trick that takes advantage of the way or works.
It works as others have described.
In PHP, do not use "die", as it does NOT raise an exception (as it does in Perl). Instead throw an exception properly in the normal way.
die cannot be caught in PHP, and does not log - instead it prints the message ungracefully and immediately quits the script without telling anybody anything or giving you any opportunity to record the event, retry etc.
If you would like to add more code if the connection doesn't work, beyond a die statement:
$con=mysql_connect($host, $user, $pass)
if(!$con)
{
// ... add extra error handling code here
die("could not connect");
}
else
{
echo "Connected";
}

Categories