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)
Related
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.
I've found several responses to this, but none pertaining to PHP (which is an extremely weak typed language):
With regards to PHP, is it appropriate to return false, null, or an empty array in a method that would usually return an array, but has a failure occur?
In other words, if another developer jumped in on my project, what would they expect to see?
An array is a collection of things. An empty array would signal that "everything went fine, there just isn't anything in that collection". If you actually want to signal an error, you should return false. Since PHP is dynamically typed, it's easy to check the return value either strictly or loosely, depending on what you need:
$result = getCollection();
if (!$result) // $result was false or empty, either way nothing useful
if ($result === false) // an actual error occurred
if ($result) // we have an array with content
There are also exceptions for error reporting in exceptional cases. It really depends on the responsibilities of the function and the severity of errors. If the role of the function allows the response "empty collection" and "nope" equally, the above may be fine. However, if the function by definition must always return a collection (even if that's empty) and in certain circumstances it cannot, throwing an exception may be a lot more appropriate than returning false.
I would strongly discourage to return mixed type return values. I consider it to be so much a problem, that i wrote a small article about not returning mixed typed values.
To answer your question, return an empty array. Below you can find a small example, why returning other values can cause problems:
// This kind of mixed-typed return value (boolean or string),
// can lead to unreliable code!
function precariousCheckEmail($input)
{
if (filter_var($input, FILTER_VALIDATE_EMAIL))
return true;
else
return 'E-Mail address is invalid.';
}
// All this checks will wrongly accept the email as valid!
$result = precariousCheckEmail('nonsense');
if ($result == true)
print('OK'); // -> OK will be given out
if ($result)
print('OK'); // -> OK will be given out
if ($result === false)
print($result);
else
print('OK'); // -> OK will be given out
if ($result == false)
print($result);
else
print('OK'); // -> OK will be given out
Hope this helps preventing some misunderstandings.
Just speaking for myself, I normally prefer to return an empty array, because if the function always returns an array, it's safe to use it with PHP's array functions and foreach (they'll accept empty arrays). If you return null or false, then you'll have to check the type of the result before passing it to an array function.
If you need to distinguish between the case where the method executed correctly but didn't find any results, and the case where an error occurred in the method, then that's where exceptions come in. In the former case it's safe to return an empty array. In the latter simply returning an empty array is insufficient to notify you of the fact an error occurred. However if you return something other than an array then you'll have to deal with that in the calling code. Throwing an exception lets you handle errors elsewhere in an appropriate error handler and lets you attach a message and a code to the exception to describe why the failure happened.
The below pseudo-code will simply return an empty array if we don't find anything of interest. However, if something goes wrong when processing the list of things we got back then an exception is thrown.
method getThings () {
$things = array ();
if (get_things_we_are_interested_in ()) {
$things [] = something_else ();
}
if (!empty ($things)) {
if (!process_things ($things)) {
throw new RuntimeExcpetion ('Things went wrong when I tried to process your things for the things!');
}
}
return $things;
}
Here's a modern answer that's been valid since the 1960's probably.
Some bad design choices in the earliest versions of PHP (before PHP 4) have made many PHP developers exposed to conventions that have always been bad. Fortunately, PHP 5 have come and gone - which helped guide many PHP developers on to the "right path".
PHP 7 is now seeing the benefits of having been through the PHP 5 phase - it is one of the fastest performing script languages in existence.
and this has made it possible to make PHP 7 one of the fastest and most powerful scripting languages in existence.
Since PHP version 4, huge efforts have been made by PHP core developers to gradually improve the PHP language. Many things remain, because we still want to have some backward compatability.
DON'T return false on error
The only time you can return FALSE in case of error, is if your function is named something like isEverythingFine().
false has always been the wrong value to return for errors. The reason you still see it in PHP documentation, is because of backward compatability.
It would be inconsistent. What do you return on error in those cases where your function is supposed to return a boolean true or false?
If your function is supposed to return something other than booleans, then you force yourself to write code to handle type checking. Since many people don't do type checking, the PHP opcode compiler is also forced to write opcodes that does type checking as well. You get double type checking!
You may return null
Most scripting languages have made efficient provisions for the null value in their data types. Ideally, you don't even use that value type - but if you can't throw an exception, then I would prefer null. It is a valid "value" for all data types in PHP - even if it is not a valid value internally in the PC.
Optimally for the computer/CPU is that the entire value is located in a single 1, 2, 4 or 8 byte memory "cell". These value sizes are common for all native value types.
When values are allowed to be null, then this must be encoded in a separate memory cell and whenever the computer needs to pass values to a function or return them, it must return two values. One containing isNull and another for the value.
You may return a special value depending on type
This is not ideal, because
If your function is supposed to return an integer, then return -1.
If your function is supposed to return a string
You should throw exceptions
Exceptions match the inner workings of most CPUs. They have a dedicated internal flag to declare that an exceptional event occurred.
It is highly efficient, and even if it wasn't we have gigantic benefits of not having a lot of extra work in the normal non-erroneous situation.
It depends on the situation and how bad the error is, but a good (and often overlooked) option is to throw an exception:
<?php
function inverse($x) {
if (!$x) {
throw new Exception('Division by zero.');
}
else return 1/$x;
}
try {
echo inverse(5) . "\n";
echo inverse(0) . "\n";
} catch (Exception $e) {
echo 'Caught exception: ', $e->getMessage(), "\n";
}
This will ensure that your function will not fail silently and errors won't go unseen.
I assume that the return type of your method is array, so you should return an empty array only if the execution went fine but no results were found.
In case of an error, you should throw an exception. This should be the preferred way to handle errors.
If there's really a problem then you should raise an error, otherwise if the criteria aren't met etc then return a blank array.
Whichever you prefer, though I suggest an empty array for the for a good reason. You don't have to check the type first!
<?php
function return_empty_array() {
return array();
}
$array = return_empty_array();
// there are no values, thus code within doesn't get executed
foreach($array as $key => $value) {
echo $key . ' => ' . $value . PHP_EOL;
}
?>
In any other case, if you'd return false or null, you'd get an error at the foreach loop.
It's a minuscule difference, though in my opinion a big one. I don't want to check what type of value I got, I want to assume it's an array. If there are no results, then it's an empty array.
Anyway, as far as I'm concerned there are no "defaults" for returning empty values. Native PHP functions keep amazing me with the very different values it returns. Sometimes false, sometimes null, sometimes an empty object.
I have written a function that returns data on success and false on failure.
I was wondering if this is considered a proper way of evaluating the return value in php.
function data(){
if($all_is_good){
return $data
}else{
return false;
}
}
$data = data(); //basically either a long series of strings or arrays
if(!$data){ //<-- this is the line I'm concerned about, is it safe to assume this?
echo 'oh no, bad stuff happened';
}
Thank you so much!
What you have there is fine, although alternatively, you could use if($data === false) {. This ensures that $data is actually false, considering 0 and NULL are also seen as false.
It depends in what exactly $data is (both its type and its value). It makes sense both to leave it as-is (if the type of the value in $data is not certain) or make the check explicit (e.g. $data == false or empty($data)) if it's a known type. It's really dependent on the specific circumstances.
See Converting to boolean.
It is safe unless there is a valid value for $data that would evaluate to false. A long (i.e. nonempty) series of strings or arrays won't evaluate to false, but still it's a potential pitfall.
You might consider using a strict comparison: if(data===False)
I was turned on to nstrees from another question, and have been working through the script. It was last updated in 2005 and relied on some stuff that has since apparently been deprecated like HTTP_POST_VARS which I wasn't immediately familiar with since I've been doing PHP for only a little less than a year.
Anyways, the coding style seems weird to my rookie eyes, and I'd like a second opinion on what part of this function does:
// returns the first node that matches the '$whereclause'.
// The WHERE clause can optionally contain ORDER BY or LIMIT clauses too.
function nstGetNodeWhere ($thandle, $whereclause) {
$noderes['l'] = 0;
$noderes['r'] = 0;
$res = mysql_query("SELECT * FROM ".$thandle['table']." WHERE ".$whereclause);
if (!$res) { // problem area 1
_prtError();
} else {
if ($row = mysql_fetch_array($res)) { // problem area 2
$noderes['l'] = $row[$thandle['lvalname']];
$noderes['r'] = $row[$thandle['rvalname']];
}
}
return $noderes;
}
In the above code I marked the spots I'm not quite sure about as // problem area x, everything else is the original script.
Regarding PA1, is that just a check on whether the query was successfully run?
And PA2, NetBeans gives me a warning "Possible accidental assignment, assignments in conditions should be avoided." ... so I promptly changed that from = to == and of course broke the script, heh.
Thinking about it, I guess it's just another error check on $res, this time to make sure that some data was actually returned?
Lastly, is this bizarre PHP or am I just too green to grok it?
Thanks dude(tte)s!
Problem Area 1 is exactly what you think it is. It checks if the query ran successfully. Look at the documentation for mysql_query (since you use Netbeans you can also highlight the function name in the editor and hit F2 to get an inline popup). You're looking for the "Return Values" section. Over there it says it will return FALSE (the boolean FALSE) on any errors.
Checking
if (!$res)
is the same as checking for
if ($res == false)
Ideally you should be checking for
if ($res === false)
because it's safer since PHP is very relaxed about variables == false, but I'd rather not confuse you with that right now. If you'd like you can start by reading about strong typing.
Problem Area 2 is pretty common but will show a warning in Netbeans, yes. What it's doing is assigning a value from mysql_fetch_array() into $row, and checking if that is now true or false, while also letting you use that same value now in $row in the following code block inside the if().
I assume this code can load articles then sort them into a 'left-right' array so it can be printed in a two column layout. Maybe. :)
Yep, PA1 is checking if the query was successful or not. PA2 is simply fetching the actual row.
if (!$res) { // problem area 1
mysql_query returns a false if it fails to execute the SQL query. This is basically a test for not (!) any value other than false, so the if test will match if there was an error in mysql_query and execute the print error branch of the code
if ($row = mysql_fetch_array($res)) { // problem area 2
Assigns the next row from the resultset to $row; or sets $row to false if no more rows in the resultset, in which case the "if test" will be false
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";
}