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).

Використання круглих дужок, навіть коли це не є обов'язковим, часто може покращити читабельність коду, роблячи групування явним, а не покладаючись на неявні оператори пріоритету та асоціативності.

У наступній таблиці перераховані оператори в порядку пріоритету, з операторами з найвищим пріоритетом зверху. Оператори в одному рядку мають однаковий пріоритет, у цьому випадку асоціативність визначає групування.

Operator Precedence Associativity Operators Additional Information (n/a) clone new clone and new right ** arithmetic (n/a) + - ++ -- ~ (int) (float) (string) (array) (object) (bool) @ arithmetic (unary + and -), increment/decrement, bitwise, type casting and error control left instanceof type (n/a) ! logical left * / % arithmetic left + - . arithmetic (binary + and -), array and string (. prior to PHP 8.0.0) left << >> bitwise left . string (as of PHP 8.0.0) non-associative < <= > >= comparison non-associative == != === !== <> <=> comparison left & bitwise and references left ^ bitwise left | bitwise left && logical left || logical right ?? null coalescing non-associative ? : ternary (left-associative prior to PHP 8.0.0) right = += -= *= **= /= .= %= &= |= ^= <<= >>= ??= assignment (n/a) yield from yield from (n/a) yield yield (n/a) print print left and logical left xor logical left or logical

Приклад №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.

Version Description 8.0.0 String concatenation (.) 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 >>. 8.0.0 The ternary operator (? :) is non-associative now; previously it was left-associative. 7.4.0 Relying on the precedence of string concatenation (.) relative to arithmetic addition/subtraction (+ or -) or bitwise shift left/right (<< or >>), i.e. using them together in an unparenthesized expression, is deprecated. 7.4.0 Relying on left-associativity of the ternary operator (? :), i.e. nesting multiple unparenthesized ternary operators, is deprecated.