tags:

views:

696

answers:

11

As the title says: Is there a difference between $str == '' and strlen($str) == 0 in PHP? Is there any real speed difference and is one better to use than the other?

+1  A: 

$str == '' is better practice. There probably isn't much difference in PHP, since it knows the length of its strings, but it'd be a really bad habit to have if you then went and did some work in a lower-level language.

chaos
+1  A: 

The speed difference is too small to matter, I'm sure. The best method to use is the more readable one. Here are two other alternatives:

if (empty($str)) {
    ...
}

if (!$str) {
    ...
}

Note: These will both evaluate to true if $str == '0'.

yjerem
Those examples aren't correct. empty('0') == empty('') is true
jmucchiello
Yes, same with '!$str', but this almost always works for the code I'm writing.
yjerem
Yes but this is a place where correct answers should be given. Not answers that almost always work in the code you write.
jmucchiello
Do not use Empty for comparing if a string has no data.. Bad habit you have.
Daok
Alright, I added a note about it to my answer.
yjerem
+1  A: 

Maybe: !strlen($str)

tunnuz
+1  A: 

strlen($str) == 0 requires a call to strlen and a call to do the comparison. $str == '' is just a comparison.

jmucchiello
Don't you meant $str == '' ?
strager
+1  A: 

There might be some type-conversion issues when doing $str==''. For example, consider cases when $str is false (boolean) or 0 (integer). They might just come out equal too. I'm not exactly sure about this, so you should muck around with it a bit. The safe way would be to do $str===''.

Vilx-
The type conversion will also happen when you call strlen(false) or strlen(0). If $str is false, false == '' is true. false === '' is false.
jmucchiello
+2  A: 

Even if there was a speed difference, you should not pick the faster one. Pick the clearer one.

Pyrolistical
+8  A: 

Yes, there is an important difference. The == operator does type conversion, so it's not always going to do what you expect. For example, (0 == "") returns true. So you're making an assumption that $str is actually a string. If you're sure this is the case, or if you don't care about the conversions, then it's fine. Otherwise you should use ===, and take steps to ensure that you're comparing strings.

JW
strlen($str) will also do type conversion. Sometimes it doesn't do what you expect either.
jmucchiello
It's probably worth noting that === is a PHP5 feature (theres still PHP4 code/projects out there).
cletus
The === operator is NOT a php5 only feature. It was <a href="http://us3.php.net/language.operators.comparison">introduced in PHP4</a>
Alan Storm
Let's try that sans hyper text http://us3.php.net/language.operators.comparison
Alan Storm
+5  A: 

The main difference is that $str == '' will return true for anything that's equivalent to the empty string (0 and false, among others).

You should use either the === operator to test for an actual empty string or, if you don't mind the convert and test behavior, just use !$str (consider empty() as well, depending on the actual intent), which I find clearer in intent than $x == '' (Did he miss an = sign and actually wants to test for an empty string?.)

Use strlen($str) only when you really are after the length of a string.

Bottom line, use the proper tool for the job, judging which tool is proper based on the intent of the code.

vinko@parrot:~$ cat emptytest.php
<?php
$a = "";
$b = 0;
$c = false;
$d = "Hi!";

function is_empty1($x) { return $x == ''; }
function is_empty2($x) { return strlen($x) == 0; }
function is_empty3($x) { return $x === ''; }

function check_empty($arr) {
        foreach ($arr as $v) {
                echo "value is ";
                var_dump($v);
                echo "   \$x == ''      ";
                var_dump(is_empty1($v));
                echo "   strlen($x) == 0 ";
                var_dump(is_empty2($v));
                echo "   \$x === ''     ";
                var_dump(is_empty3($v));
        }
}

check_empty(array($a,$b,$c,$d));

?>
vinko@parrot:~$ php emptytest.php
value is string(0) ""
   $x == ''      bool(true)
   strlen() == 0 bool(true)
   $x === ''     bool(true)
value is int(0)
   $x == ''      bool(true)
   strlen() == 0 bool(false)
   $x === ''     bool(false)
value is bool(false)
   $x == ''      bool(true)
   strlen() == 0 bool(true)
   $x === ''     bool(false)
value is string(3) "Hi!"
   $x == ''      bool(false)
   strlen() == 0 bool(false)
   $x === ''     bool(false)
Vinko Vrsalovic
If $x is false and you call strlen($x), $x will be converted to an empty string and its length will be 0. strlen($x) == 0 is NOT equivalent to ===. Use === if that is the behavior you want.
jmucchiello
Yes. Removed that example. Those 'really really equal' and 'not so equal but equal' operators are annoying at best.
Vinko Vrsalovic
+4  A: 

I performed a simple benchmark. (I've never done one so this may be completely invalid.) It tests == '', strlen() == 0, === '', and strlen() === 0.

header('Content-type: text/plain');

// -- Testing == '';

$string = '';

$startTime = microtime(true);
for($i = 0; $i < 10000000; ++$i)
    $string == '';
$endTime = microtime(true);
echo "\$string = ''; \$string == ''; took " . ($endTime - $startTime) . " seconds\n";

$string = 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa';

$startTime = microtime(true);
for($i = 0; $i < 10000000; ++$i)
    $string == '';
$endTime = microtime(true);
echo "\$string = '$string'; \$string == ''; took " . ($endTime - $startTime) . " seconds\n";

$startTime = microtime(true);
for($i = 0; $i < 10000000; ++$i)
    '' == '';
$endTime = microtime(true);
echo "'' == ''; took " . ($endTime - $startTime) . " seconds\n";

// -- Testing strlen() == 0;

$string = '';

$startTime = microtime(true);
for($i = 0; $i < 10000000; ++$i)
    strlen($string) == 0;
$endTime = microtime(true);
echo "\$string = ''; strlen(\$string) == 0; took " . ($endTime - $startTime) . " seconds\n";

$string = 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa';

$startTime = microtime(true);
for($i = 0; $i < 10000000; ++$i)
    strlen($string) == 0;
$endTime = microtime(true);
echo "\$string = '$string'; strlen(\$string) == 0; took " . ($endTime - $startTime) . " seconds\n";

$startTime = microtime(true);
for($i = 0; $i < 10000000; ++$i)
    strlen('') == 0;
$endTime = microtime(true);
echo "strlen('') == ''; took " . ($endTime - $startTime) . " seconds\n";

// -- Testing === '';

$string = '';

$startTime = microtime(true);
for($i = 0; $i < 10000000; ++$i)
    $string === '';
$endTime = microtime(true);
echo "\$string = ''; \$string === ''; took " . ($endTime - $startTime) . " seconds\n";

$string = 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa';

$startTime = microtime(true);
for($i = 0; $i < 10000000; ++$i)
    $string === '';
$endTime = microtime(true);
echo "\$string = '$string'; \$string === ''; took " . ($endTime - $startTime) . " seconds\n";

$startTime = microtime(true);
for($i = 0; $i < 10000000; ++$i)
    '' === '';
$endTime = microtime(true);
echo "'' === ''; took " . ($endTime - $startTime) . " seconds\n";

// -- Testing strlen() === 0;

$string = '';

$startTime = microtime(true);
for($i = 0; $i < 10000000; ++$i)
    strlen($string) === 0;
$endTime = microtime(true);
echo "\$string = ''; strlen(\$string) === 0; took " . ($endTime - $startTime) . " seconds\n";

$string = 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa';

$startTime = microtime(true);
for($i = 0; $i < 10000000; ++$i)
    strlen($string) === 0;
$endTime = microtime(true);
echo "\$string = '$string'; strlen(\$string) === 0; took " . ($endTime - $startTime) . " seconds\n";

$startTime = microtime(true);
for($i = 0; $i < 10000000; ++$i)
    strlen('') === 0;
$endTime = microtime(true);
echo "strlen('') === ''; took " . ($endTime - $startTime) . " seconds\n";

Results:

$string = ''; $string == ''; took 1.01983308792 seconds
$string = 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'; $string == ''; took 1.04193401337 seconds
'' == ''; took 1.06608295441 seconds
$string = ''; strlen($string) == 0; took 2.1510848999 seconds
$string = 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'; strlen($string) == 0; took 2.27101397514 seconds
strlen('') == ''; took 2.5775551796 seconds
$string = ''; $string === ''; took 0.854554176331 seconds
$string = 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'; $string === ''; took 0.714010000229 seconds
'' === ''; took 0.749495983124 seconds
$string = ''; strlen($string) === 0; took 1.9263010025 seconds
$string = 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'; strlen($string) === 0; took 1.95309996605 seconds
strlen('') === ''; took 2.40874910355 seconds

As you can see, comparing to '' is about twice as fast as comparing the length of the string. Also, using === is slightly faster than using ==, and it's type safe! Nice.

strager
I like the first two results. My answer says strlen($x) == 0 is two ops and $str == 0 is one op. Thanks for confirming two ops takes roughly twice as long as one op. :-)
jmucchiello
+1  A: 

No, they're not the same (as explained above), but for your purposes they might be interchangeable.

Faster? Qualitatively, it's hard to imagine a situation where the difference either way would be consequential, but see other more quantitative answers. Coding based on speed here is probably an example of our favorite pejorative, which can be abbrevated "pi".

Which is best?

It depends on what assertion about $str you want to confirm, and what consequence you want to invoke.

Another common pattern you'll see is

!$str

which gives generally the same result - and may be appropriate if you simply want to test for a string value that is unusable, no matter why it's unusable - which could be lack of initialization, initialization default, assignment, etc. (I'm not arguing for or against this representation, BTW.) Remember that what you decide will presumably have consequences, and you need to understand what $str states invoke which consequences, based on the way you've written the code. (And notice there are $str value/states which you might not have explicitly covered with either of our options.)

le dorfier
A: 

i find it clearer to just do "if (!$str)" .. not sure about '==' but '!' should be able to yeld better optimization techniques, as no typecasting is ever done, and is safe for strings, arrays, bools, numbers...

Quamis