Есть ли разница между $str == '' и strlen($str) == 0 в PHP?

Как следует из названия: есть ли разница между $str == '' и strlen($str) == 0 в PHP? Есть ли реальная разница в скорости и лучше ли использовать один, чем другой?


person Darryl Hein    schedule 19.12.2008    source источник


Ответы (11)


Да, есть важное отличие. Оператор == выполняет преобразование типов, поэтому он не всегда будет делать то, что вы ожидаете. Например, (0 == "") возвращает true. Итак, вы делаете предположение, что $str на самом деле является строкой. Если вы уверены, что это так, или если вас не волнуют конверсии, то все в порядке. В противном случае вы должны использовать === и предпринять шаги, чтобы убедиться, что вы сравниваете строки.

person JW.    schedule 19.12.2008
comment
strlen($str) также выполняет преобразование типов. Иногда это не делает то, что вы ожидаете. - person jmucchiello; 19.12.2008
comment
Вероятно, стоит отметить, что === - это функция PHP5 (все еще есть код/проекты PHP4). - person cletus; 20.12.2008
comment
Оператор === НЕ является функцией только php5. Это было ‹a href=us3.php.net/language.operators.comparison›введено в PHP4‹/a› - person Alan Storm; 20.12.2008

я считаю более ясным просто сделать "if (!$str)" .. не уверен насчет '==', но '!' должен иметь возможность использовать лучшие методы оптимизации, поскольку приведение типов никогда не выполняется и безопасно для строк, массивов, логических значений, чисел...

person Quamis    schedule 19.12.2008

Основное отличие состоит в том, что $str == '' вернет true для всего, что эквивалентно пустой строке (0 и false, среди прочих).

Вы должны использовать либо оператор === для проверки фактической пустой строки, либо, если вы не возражаете против преобразования и поведения теста, просто используйте !$str (рассмотрите empty(), в зависимости от фактического намерения), что я нахожу более ясным в намерении, чем $x == '' (он пропустил знак = и действительно хочет проверить пустую строку?.)

Используйте strlen($str) только тогда, когда вам действительно нужна длина строки.

В итоге используйте правильный инструмент для работы, судя по тому, какой инструмент подходит, исходя из цели кода.

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)
person Vinko Vrsalovic    schedule 19.12.2008
comment
Если $x имеет значение false и вы вызываете strlen($x), $x будет преобразована в пустую строку и ее длина будет равна 0. strlen($x) == 0 НЕ эквивалентно ===. Используйте ===, если это поведение, которое вы хотите. - person jmucchiello; 19.12.2008
comment
Да. Удалил этот пример. Эти «действительно равные» и «не совсем равные, но равные» операторы в лучшем случае раздражают. - person Vinko Vrsalovic; 19.12.2008

Я провел простой тест. (Я никогда не делал этого, так что это может быть совершенно недействительным.) Он проверяет == '', strlen() == 0, === '' и 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";

Полученные результаты:

$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

Как видите, сравнение с '' происходит примерно в два раза быстрее, чем сравнение длины строки. Кроме того, использование === немного быстрее, чем использование ==, и это безопасно для типов! Хороший.

person strager    schedule 19.12.2008
comment
Мне нравятся первые два результата. Мой ответ говорит, что strlen($x) == 0 - это две операции, а $str == 0 - одна операция. Спасибо, что подтвердили, что две операции занимают примерно в два раза больше времени, чем одна операция. :-) - person jmucchiello; 19.12.2008

Даже если была разница в скорости, не следует выбирать более быструю. Выберите более четкое.

person Pyrolistical    schedule 19.12.2008
comment
Вы имеете в виду более понятный человеку? - person ryanve; 03.12.2011
comment
@ryanve да, это то, что я имею в виду - person Pyrolistical; 07.05.2012

$str == '' - лучшая практика. Вероятно, в PHP нет большой разницы, поскольку он знает длину своих строк, но было бы очень плохой привычкой, если бы вы затем пошли и поработали на языке более низкого уровня.

person chaos    schedule 19.12.2008

Возможно: !strlen($str)

person tunnuz    schedule 19.12.2008

strlen($str) == 0 требует вызова strlen и вызова для сравнения. $str == '' - это просто сравнение.

person jmucchiello    schedule 19.12.2008

При выполнении $str=='' могут возникнуть проблемы с преобразованием типов. Например, рассмотрим случаи, когда $str равно false (логическое значение) или 0 (целое число). Они могут просто оказаться равными тоже. Я не совсем уверен в этом, так что вам следует немного повозиться с этим. Безопасным способом было бы сделать $str===''.

person Vilx-    schedule 19.12.2008
comment
Преобразование типа также произойдет, когда вы вызовете strlen(false) или strlen(0). Если $str ложно, false == '' истинно. ложь === '' является ложью. - person jmucchiello; 19.12.2008

Разница в скорости слишком мала, чтобы иметь значение, я уверен. Лучший метод для использования является более читабельным. Вот еще две альтернативы:

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

if (!$str) {
    ...
}

Примечание. Они оба оцениваются как истинные, если $str == '0'.

person Paige Ruten    schedule 19.12.2008
comment
Эти примеры неверны. пустой('0') == пустой('') верно - person jmucchiello; 19.12.2008
comment
Да, то же самое с '!$str', но это почти всегда работает для кода, который я пишу. - person Paige Ruten; 19.12.2008
comment
Да, но это место, где должны быть даны правильные ответы. Не ответы, которые почти всегда работают в коде, который вы пишете. - person jmucchiello; 19.12.2008
comment
Не используйте Empty для сравнения, если в строке нет данных. У вас плохая привычка. - person Patrick Desjardins; 19.12.2008

Нет, они не одинаковы (как объяснялось выше), но для ваших целей они могут быть взаимозаменяемыми.

Быстрее? Качественно трудно представить ситуацию, в которой разница в любом случае была бы существенной, но посмотрите другие, более количественные ответы. Кодирование, основанное на скорости, здесь, вероятно, является примером нашего любимого уничижительного выражения, которое можно сокращать до «пи».

Что лучше?

Это зависит от того, какое утверждение о $str вы хотите подтвердить и какое последствие вы хотите вызвать.

Другой распространенный шаблон, который вы увидите, это

!$стр

который обычно дает тот же результат - и может быть уместным, если вы просто хотите проверить строковое значение, которое непригодно для использования, независимо от того, почему оно непригодно для использования, что может быть отсутствие инициализации, инициализация по умолчанию, назначение и т. д. (я не спорить за или против этого представления, BTW.) Помните, что то, что вы решите, предположительно будет иметь последствия, и вам нужно понять, какие состояния $str вызывают какие последствия, исходя из того, как вы написали код. (И обратите внимание, что есть значения/состояния $str, которые вы, возможно, не указали явно ни в одном из наших вариантов.)

person dkretz    schedule 19.12.2008