Как следует из названия: есть ли разница между $str == '' и strlen($str) == 0 в PHP? Есть ли реальная разница в скорости и лучше ли использовать один, чем другой?
Есть ли разница между $str == '' и strlen($str) == 0 в PHP?
Ответы (11)
Да, есть важное отличие. Оператор == выполняет преобразование типов, поэтому он не всегда будет делать то, что вы ожидаете. Например, (0 == "") возвращает true. Итак, вы делаете предположение, что $str на самом деле является строкой. Если вы уверены, что это так, или если вас не волнуют конверсии, то все в порядке. В противном случае вы должны использовать === и предпринять шаги, чтобы убедиться, что вы сравниваете строки.
я считаю более ясным просто сделать "if (!$str)" .. не уверен насчет '==', но '!' должен иметь возможность использовать лучшие методы оптимизации, поскольку приведение типов никогда не выполняется и безопасно для строк, массивов, логических значений, чисел...
Основное отличие состоит в том, что $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)
Я провел простой тест. (Я никогда не делал этого, так что это может быть совершенно недействительным.) Он проверяет == '', 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
Как видите, сравнение с '' происходит примерно в два раза быстрее, чем сравнение длины строки. Кроме того, использование === немного быстрее, чем использование ==, и это безопасно для типов! Хороший.
Даже если была разница в скорости, не следует выбирать более быструю. Выберите более четкое.
$str == '' - лучшая практика. Вероятно, в PHP нет большой разницы, поскольку он знает длину своих строк, но было бы очень плохой привычкой, если бы вы затем пошли и поработали на языке более низкого уровня.
Возможно: !strlen($str)
strlen($str) == 0 требует вызова strlen и вызова для сравнения. $str == '' - это просто сравнение.
При выполнении $str==''
могут возникнуть проблемы с преобразованием типов. Например, рассмотрим случаи, когда $str
равно false
(логическое значение) или 0
(целое число). Они могут просто оказаться равными тоже. Я не совсем уверен в этом, так что вам следует немного повозиться с этим. Безопасным способом было бы сделать $str===''
.
Разница в скорости слишком мала, чтобы иметь значение, я уверен. Лучший метод для использования является более читабельным. Вот еще две альтернативы:
if (empty($str)) {
...
}
if (!$str) {
...
}
Примечание. Они оба оцениваются как истинные, если $str == '0'.
Нет, они не одинаковы (как объяснялось выше), но для ваших целей они могут быть взаимозаменяемыми.
Быстрее? Качественно трудно представить ситуацию, в которой разница в любом случае была бы существенной, но посмотрите другие, более количественные ответы. Кодирование, основанное на скорости, здесь, вероятно, является примером нашего любимого уничижительного выражения, которое можно сокращать до «пи».
Что лучше?
Это зависит от того, какое утверждение о $str вы хотите подтвердить и какое последствие вы хотите вызвать.
Другой распространенный шаблон, который вы увидите, это
!$стр
который обычно дает тот же результат - и может быть уместным, если вы просто хотите проверить строковое значение, которое непригодно для использования, независимо от того, почему оно непригодно для использования, что может быть отсутствие инициализации, инициализация по умолчанию, назначение и т. д. (я не спорить за или против этого представления, BTW.) Помните, что то, что вы решите, предположительно будет иметь последствия, и вам нужно понять, какие состояния $str вызывают какие последствия, исходя из того, как вы написали код. (И обратите внимание, что есть значения/состояния $str, которые вы, возможно, не указали явно ни в одном из наших вариантов.)