Operator Precedence
Оновлено: 11.05.2023
Пріоритет оператора визначає, наскільки "міцно" він пов'язує два вирази разом. Наприклад, у виразі 1 + 5 * 3 відповідь буде 16, а не 18, оскільки оператор множення ("*") має вищий пріоритет, ніж оператор додавання ("+"). За необхідності можна використовувати круглі дужки для примусового встановлення пріоритету. Наприклад: (1 + 5) * 3 дає 18.
Коли оператори мають однаковий пріоритет, їхня асоціативність визначає, як вони будуть згруповані. Наприклад, "-" є лівоасоціативним, тому 1 - 2 - 3 групується як (1 - 2) - 3 і обчислюється до -4. "=", з іншого боку, є правоасоціативним, тому $a = $b = $c групується як $a = ($b = $c).
Оператори з однаковим пріоритетом, які не є асоціативними, не можна використовувати один біля одного, наприклад, 1 < 2 > 1 є незаконним у PHP. З іншого боку, вираз 1 <= 1 == 1 є легальним, оскільки оператор == має нижчий пріоритет, ніж оператор <=.
Асоціативність має сенс лише для бінарних (і тернарних) операторів. Унарні оператори є або префіксними, або постфіксними, тому це поняття не застосовується. Наприклад, !!$a можна згрупувати лише як !(!$a).
Використання круглих дужок, навіть коли це не є обов'язковим, часто може покращити читабельність коду, роблячи групування явним, а не покладаючись на неявні оператори пріоритету та асоціативності.
У наступній таблиці перераховані оператори в порядку пріоритету, з операторами з найвищим пріоритетом зверху. Оператори в одному рядку мають однаковий пріоритет, у цьому випадку асоціативність визначає групування.
clone
new
**
+
-
++
--
~
(int)
(float)
(string)
(array)
(object)
(bool)
@
+
and -
),
increment/decrement,
bitwise,
type casting and
error control
instanceof
!
*
/
%
+
-
.
+
and -
),
array and
string (.
prior to PHP 8.0.0)
<<
>>
.
<
<=
>
>=
==
!=
===
!==
<>
<=>
&
^
|
&&
||
??
? :
=
+=
-=
*=
**=
/=
.=
%=
&=
|=
^=
<<=
>>=
??=
yield from
yield
print
and
xor
or
Приклад №1 Асоціативність
<?php
$a = 3 * 3 % 5; // (3 * 3) % 5 = 4
// ternary operator associativity differs from C/C++
$a = true ? 0 : true ? 1 : 2; // (true ? 0 : true) ? 1 : 2 = 2 (prior to PHP 8.0.0)
$a = 1;
$b = 2;
$a = $b += 3; // $a = ($b += 3) -> $a = 5, $b = 5
?>
Оператори пріоритету та асоціативності визначають лише спосіб групування виразів, вони не визначають порядок обчислення. PHP не визначає (у загальному випадку), в якому порядку обчислюється вираз, і слід уникати коду, який передбачає певний порядок обчислення, оскільки поведінка може змінюватися між версіями PHP або в залежності від оточуючого коду.
Приклад #2 Невизначений порядок оцінювання
<?php
$a = 1;
echo $a + $a++; // may print either 2 or 3
$i = 1;
$array[$i] = $i++; // may set either index 1 or 2
?>
Приклад #3 +, - та . мають однаковий пріоритет (до версії PHP 8.0.0)
<?php
$x = 4;
// this line might result in unexpected output:
echo "x minus one equals " . $x-1 . ", or so I hope\n";
// because it is evaluated like this line (prior to PHP 8.0.0):
echo (("x minus one equals " . $x) - 1) . ", or so I hope\n";
// the desired precedence can be enforced by using parentheses:
echo "x minus one equals " . ($x-1) . ", or so I hope\n";
?>
Вищенаведений приклад виведе:
Зауважте:
Хоча = має нижчий пріоритет, ніж більшість інших операторів, PHP все одно допускає вирази, подібні до наступного: if (!$a = foo()), в якому значення, що повертається функцією foo(), поміщається в $a.
.
) now has a lower precedence than
arithmetic addition/subtraction (+
and -
) and
bitwise shift left/right (<<
and >>
);
previously it had the same precedence as +
and -
and a higher precedence than <<
and >>
.
? :
) is non-associative now;
previously it was left-associative.
.
) relative to
arithmetic addition/subtraction (+
or -
) or
bitwise shift left/right (<<
or >>
),
i.e. using them together in an unparenthesized expression, is deprecated.
? :
),
i.e. nesting multiple unparenthesized ternary operators, is deprecated.