It seems like my code works to check for null if I do
if ($tx)
or
if (isset($tx))
why would I do the se
The first one only works depending on how your server is configured. On many production servers, it will break.
Use isset()
and be merry.
Or, try your code with the following at the top of the PHP source and watch it break:
ini_set('display_errors', 1);
error_reporting(E_ALL);
if ($tx)
This code will evaluate to false for any of the following conditions:
unset($tx); // not set, will also produce E_WARNING
$tx = null;
$tx = 0;
$tx = '0';
$tx = false;
$tx = array();
The code below will only evaluate to false under the following conditions:
if (isset($tx))
// False under following conditions:
unset($tx); // not set, no warning produced
$tx = null;
For some people, typing is very important. However, PHP by design is very flexible with variable types. That is why the Variable Handling Functions have been created.
Because the former could also check for true/false, which you may or may not want.
These two are quite different, as every single answer has pointed out. If you do not use isset, many things will evaluate to false, especially arrays, values of false, numeric values of 0 (and others), etc. True that.
It seems strange to me that everyone is so quick to defend correct programming in PHP. If I want to do correct programming, I've got tons of statically-typed, strongly-typed languages to do it with. It seems to me that one advantage to PHP is that I don't have to think about types that much. Sure, there are cases where
if ($tx)
evaluates to false when it in fact does have a value, but if you want to check if it's a Transaction Object or not, it either works or it doesn't. It turns out that, with the Doctrine framework, this code
if (isset($tx))
always evaluates to true after grabbing the first object of a query. I instead have to say
if ($tx instanceof PurchaseRecord)
So my point is that in PHP, you know what you're testing for! For instance, if it's a parameter from a GET request, it will either be null, empty, or have a value. You must handle these three cases. Or two cases, or whatever number of cases you have in your particular code. Once you have, if it works on your development server and it works on your production server, maybe you can say that it works and get on with your life?
(In Java or C#, it has to compile and then run without throwing Exceptions. Most NullPointer exceptions in Java actually get thrown with no problems being caused: Java APIs cannot possibly check for all nulls in code because it's impossible, and also because it's no problem. If it compiles and works when it's supposed to, you know your code is okay. Then later you can worry about throwing more correct Exceptions.)
If at all points you have to know what the underlying types of your code in PHP, why not code using types in the first place? Or more to the point, why not take advantage of the looseness of PHP and code with code that runs.
I want to point out that everyone's reponse I've read here should have one caveat added:
"isset() will return FALSE if testing a variable that has been set to NULL" (php.net/isset).
This means that in some cases, like checking for a GET or POST parameter, using isset() is enough to tell if the variable is set (because it will either be a string, or it won't be set). However, in cases where NULL is a possible value for a variable, which is fairly common when you get into objects and more complex applications, isset() leaves you high and dry.
For example (tested with PHP 5.2.6 with Suhosin-Patch 0.9.6.2 (cli) (built: Aug 17 2008 09:05:31)):
<?php
$a = '';
$b = NULL;
var_dump(isset($a));
var_dump(isset($b));
var_dump(isset($c));
outputs:
bool(true)
bool(false)
bool(false)
Thanks, PHP!
Put simply, those comparison are not the same. The first will cast the variable to a boolean, which will fail the check on empty arrays, non-numeric strings and other checks, in which the variable is definitely set. The second check (isset()) tests whether the variable exists at all.
I would never perform the first check (boolean cast) without checking the type of the variable as well.
Not to mention, the first check will throw an E_NOTICE, and I always run with at the maximum error reporting level.