Comparison Operators
Оновлено: 12.05.2023
Оператори порівняння, як випливає з їхньої назви, дозволяють порівнювати два значення. Вам також може бути цікаво переглянути таблиці порівняння типів, оскільки вони показують приклади різних порівнянь, пов'язаних з типами.
true
if $a is equal to $b after type juggling.true
if $a is equal to $b, and they are of the same
type.
true
if $a is not equal to $b after type juggling.true
if $a is not equal to $b after type juggling.true
if $a is not equal to $b, or they are not of the same
type.
true
if $a is strictly less than $b.true
if $a is strictly greater than $b.true
if $a is less than or equal to $b.true
if $a is greater than or equal to $b.Якщо обидва операнди є числовими рядками або один операнд є числом, а інший - числовим рядком, то порівняння виконується чисельно. Ці правила також застосовуються до інструкції switch. Приведення типів не відбувається, коли порівнюються === або !==, оскільки при цьому порівнюється не тільки тип, але й значення.
До версії PHP 8.0.0, якщо рядок порівнювався з числом або числовим рядком, то рядок перетворювався в число перед виконанням порівняння. Це може призвести до несподіваних результатів, як показано у наступному прикладі:
<?php
var_dump(0 == "a");
var_dump("1" == "01");
var_dump("10" == "1e1");
var_dump(100 == "1e2");
switch ("a") {
case 0:
echo "0";
break;
case "a":
echo "a";
break;
}
?>
Вивід вищенаведеного прикладу на PHP 7:
Вивід вищенаведеного прикладу на PHP 8:
<?php
// Integers
echo 1 <=> 1; // 0
echo 1 <=> 2; // -1
echo 2 <=> 1; // 1
// Floats
echo 1.5 <=> 1.5; // 0
echo 1.5 <=> 2.5; // -1
echo 2.5 <=> 1.5; // 1
// Strings
echo "a" <=> "a"; // 0
echo "a" <=> "b"; // -1
echo "b" <=> "a"; // 1
echo "a" <=> "aa"; // -1
echo "zz" <=> "aa"; // 1
// Arrays
echo [] <=> []; // 0
echo [1, 2, 3] <=> [1, 2, 3]; // 0
echo [1, 2, 3] <=> []; // 1
echo [1, 2, 3] <=> [1, 2, 1]; // 1
echo [1, 2, 3] <=> [1, 2, 4]; // -1
// Objects
$a = (object) ["a" => "b"];
$b = (object) ["a" => "b"];
echo $a <=> $b; // 0
$a = (object) ["a" => "b"];
$b = (object) ["a" => "c"];
echo $a <=> $b; // -1
$a = (object) ["a" => "c"];
$b = (object) ["a" => "b"];
echo $a <=> $b; // 1
// not only values are compared; keys must match
$a = (object) ["a" => "b"];
$b = (object) ["b" => "b"];
echo $a <=> $b; // 1
?>
Для різних типів порівняння проводиться відповідно до наступної таблиці (по порядку).
null
to "", numerical or lexical comparisonfalse
< true
Приклад #1 Порівняння булевого та нульового значень
<?php
// Bool and null are compared as bool always
var_dump(1 == TRUE); // TRUE - same as (bool)1 == TRUE
var_dump(0 == FALSE); // TRUE - same as (bool)0 == FALSE
var_dump(100 < TRUE); // FALSE - same as (bool)100 < TRUE
var_dump(-10 < FALSE);// FALSE - same as (bool)-10 < FALSE
var_dump(min(-100, -10, NULL, 10, 100)); // NULL - (bool)NULL < (bool)-100 is FALSE < TRUE
?>
Приклад #2 Транскрипція стандартного порівняння масивів
<?php
// Arrays are compared like this with standard comparison operators as well as the spaceship operator.
function standard_array_compare($op1, $op2)
{
if (count($op1) < count($op2)) {
return -1; // $op1 < $op2
} elseif (count($op1) > count($op2)) {
return 1; // $op1 > $op2
}
foreach ($op1 as $key => $val) {
if (!array_key_exists($key, $op2)) {
return 1;
} elseif ($val < $op2[$key]) {
return -1;
} elseif ($val > $op2[$key]) {
return 1;
}
}
return 0; // $op1 == $op2
}
?>
Через те, як представлені внутрішні змінні, ви не повинні перевіряти два змінні на рівність.
Додаткову інформацію див. у документації до float.
Зауваження: Майте на увазі, що жонглювання типами у PHP не завжди є очевидним при порівнянні значень різних типів, особливо при порівнянні ints з bool'ами або ints з рядками. Тому в більшості випадків рекомендується використовувати порівняння === і !==, а не == і !=.
У той час як порівняння на тотожність (=== і !==) можна застосовувати до довільних значень, інші оператори порівняння слід застосовувати лише до порівнянних значень. Результат порівняння непорівнянних значень є невизначеним, і на нього не слід покладатися.
Іншим умовним оператором є оператор "?:" (або тернарний).
Приклад #3 Присвоєння значення за замовчуванням
<?php
// Example usage for: Ternary Operator
$action = (empty($_POST['action'])) ? 'default' : $_POST['action'];
// The above is identical to this if/else statement
if (empty($_POST['action'])) {
$action = 'default';
} else {
$action = $_POST['action'];
}
?>
Середню частину тернарного оператора можна опустити. Вираз expr1 ?: expr3 обчислюється до результату expr1, якщо expr1 має значення true, і expr3 - інакше. expr1 у цьому випадку обчислюється лише один раз.
Примітка: Зверніть увагу, що тернарний оператор - це вираз, і що він обчислює не змінну, а результат виразу. Це важливо знати, якщо ви хочете повернути змінну за посиланням. Тому оператор return $var == 42 ? $a : $b; у функції повернення за посиланням не працюватиме, і буде видано попередження.
Зауважте:
Рекомендується уникати "стекування" тернарних виразів. Поведінка PHP при використанні більш ніж одного тернарного оператора без круглих дужок в одному виразі неочевидна у порівнянні з іншими мовами. Дійсно, до версії PHP 8.0.0 тернарні вирази оброблялися ліво-асоціативно, а не право-асоціативно, як у більшості інших мов програмування. Починаючи з версії PHP 7.4.0, використання лівої асоціативності є застарілим. Починаючи з версії PHP 8.0.0, тернарний оператор є неасоціативним.
Приклад #4 Неочевидна поведінка трійки
<?php
// on first glance, the following appears to output 'true'
echo (true ? 'true' : false ? 't' : 'f');
// however, the actual output of the above is 't' prior to PHP 8.0.0
// this is because ternary expressions are left-associative
// the following is a more obvious version of the same code as above
echo ((true ? 'true' : false) ? 't' : 'f');
// here, one can see that the first expression is evaluated to 'true', which
// in turn evaluates to (bool)true, thus returning the true branch of the
// second ternary expression.
?>
Зауважте:
Ланцюжок коротких терміналів (?:), однак, є стабільним і поводиться розумно. Він буде обчислювати перший аргумент, який отримає значення, що не є хибним. Зауважте, що невизначені значення все одно будуть викликати попередження.
Приклад #5 Короткотермінальний ланцюг
<?php
echo 0 ?: 1 ?: 2 ?: 3, PHP_EOL; //1
echo 0 ?: 0 ?: 2 ?: 3, PHP_EOL; //2
echo 0 ?: 0 ?: 0 ?: 3, PHP_EOL; //3
?>
Іншим корисним оператором скорочення є оператор "??" (або нульове об'єднання).
Приклад #6 Присвоєння значення за замовчуванням
<?php
// Example usage for: Null Coalesce Operator
$action = $_POST['action'] ?? 'default';
// The above is identical to this if/else statement
if (isset($_POST['action'])) {
$action = $_POST['action'];
} else {
$action = 'default';
}
?>
Зокрема, цей оператор не видає повідомлення або попередження, якщо значення у лівій частині не існує, так само як isset(). Це особливо корисно для ключів масиву.
Зауваження: Зверніть увагу, що оператор нульового об'єднання є виразом, і що він обчислює не змінну, а результат виразу. Це важливо знати, якщо ви хочете повернути змінну за посиланням. Оператор return $foo ?? $bar; у функції повернення за посиланням не спрацює, і буде видано попередження.
Зауважте:
Нульовий оператор об'єднання має низький пріоритет. Це означає, що при змішуванні його з іншими операторами (такими як конкатенація рядків або арифметичні оператори), скоріш за все, будуть потрібні круглі дужки.
<?php
// Raises a warning that $name is undefined.
print 'Mr. ' . $name ?? 'Anonymous';
// Prints "Mr. Anonymous"
print 'Mr. ' . ($name ?? 'Anonymous');
?>
Зауважте:
Зверніть увагу, що нульовий оператор об'єднання дозволяє просте вкладання:
Приклад #7 Вкладений нульовий оператор об'єднання
<?php
$foo = null;
$bar = null;
$baz = 1;
$qux = 2;
echo $foo ?? $bar ?? $baz ?? $qux; // outputs 1
?>