PHP Conference Kansai 2025

La prioridad de los operadores

La prioridad de los operadores especifica el orden en el que deben ser analizadas las valores. Por ejemplo, en la expresión 1 + 5 * 3, el resultado es 16 y no 18, ya que la multiplicación ("*") tiene una prioridad superior a la suma ("+"). Las parentesis pueden ser utilizados para forzar la prioridad, si es necesario. Por ejemplo: (1 + 5) * 3 dará 18.

Cuando los operadores tienen una prioridad igual, su asociatividad decide la forma en que los operadores son agrupados. Por ejemplo, "-" es una asociatividad por la izquierda, así 1 - 2 - 3 es agrupado de esta manera (1 - 2) - 3 y será evaluado a -4. Por otro lado, "=" es una asociatividad por la derecha, así, $a = $b = $c es agrupado de esta manera $a = ($b = $c).

Los operadores, cuya prioridad es igual, que no son asociativos, no pueden ser utilizados entre ellos, por ejemplo, 1 < 2 > 1 está prohibido en PHP. La expresión 1 <= 1 == 1 por el contrario, está permitida, ya que el operador == tiene una precedencia inferior al operador <=.

La asociatividad tiene sentido únicamente para los operadores binarios (y ternarios). Los operadores unitarios son prefijos o sufijos, por lo que esta noción no es aplicable. Por ejemplo !!$a puede ser agrupado únicamente de la siguiente manera !(!$a).

El uso de parentesis, incluso cuando no son necesarios, permite mejorar la legibilidad del código realizando agrupamientos explícitos en lugar de imaginar la prioridad de los operadores y sus asociatividades.

La tabla siguiente lista los operadores por orden de prioridad, con la prioridad más alta en la parte superior. Los operadores en la misma línea tienen una prioridad equivalente (por lo tanto, la asociatividad decide el agrupamiento).

Prioridad de los operadores
Asociatividad Operadores Información adicional
(n/a) clone new clone y new
derecha ** aritmética
(n/a) + - ++ -- ~ (int) (float) (string) (array) (object) (bool) @ aritmética (unario + y -), incremento/decremento a nivel de bits, conversión de tipo y control de errores
izquierda instanceof tipo
(n/a) ! lógico
izquierda * / % aritmética
izquierda + - . aritmética (binario + y -), array y string (. anterior a PHP 8.0.0)
izquierda << >> bitwise
izquierda . string (a partir de PHP 8.0.0)
no asociativo < <= > >= comparación
no asociativo == != === !== <> <=> comparación
izquierda & bitwise y referencias
izquierda ^ bitwise
izquierda | bitwise
izquierda && lógico
izquierda || lógico
derecha ?? coalescencia nula
no asociativo ? : ternario (izquierda--asociativo anterior a PHP 8.0.0)
derecha = += -= *= **= /= .= %= &= |= ^= <<= >>= ??= asignación
(n/a) yield from yield from
(n/a) yield yield
(n/a) print print
izquierda and lógico
izquierda xor lógico
izquierda or lógico

Ejemplo #1 Asociatividad

<?php
$a
= 3 * 3 % 5; // (3 * 3) % 5 = 4
// La asociatividad de los operadores ternarios difiere de C/C++
var_dump($a);

$a = 1;
$b = 2;
$a = $b += 3; // $a = ($b += 3) -> $a = 5, $b = 5
var_dump($a, $b);
?>

El operador ternario requiere específicamente el uso de parentesis para levantar la ambigüedad de la prioridad.

Ejemplo #2 Precedencia explícita

<?php
$a
= true ? 0 : (true ? 1 : 2);
var_dump($a);

// Esto ya no está permitido a partir de PHP 8
// $a = true ? 0 : true ? 1 : 2;
?>

La prioridad y la asociatividad del operador determinan únicamente la forma en que las expresiones son agrupadas; no especifican el orden de la evaluación. PHP no especifica (de manera general) el orden en que una expresión es evaluada y el código que asume un orden específico de evaluación no debería existir, ya que el comportamiento puede cambiar entre las diferentes versiones de PHP o según el código circundante.

Ejemplo #3 Orden de evaluación indefinido

<?php
$a
= 1;
echo
$a + $a++; // puede mostrar 2 o 3

$i = 1;
$array[$i] = $i++; // puede definir el índice 1 o 2
?>

Ejemplo #4 Precedencia de +, - y .

<?php
$x
= 4;

// Esta línea puede causar una salida inesperada :
echo "x menos uno es igual a" . $x-1 . ", en todo caso espero\n";

// la precedencia deseada puede ser reforzada utilizando parentesis. :
echo "x menos uno es igual a" . ($x-1) . ", en todo caso espero\n";

// Esto no está permitido, y levanta una TypeError :
echo ("x menos uno es igual a" . $x) - 1 . ", en todo caso espero\n";
?>

El resultado del ejemplo sería:

-1, en todo caso espero
-1, en todo caso espero
Fatal error: Uncaught TypeError: Unsupported operand types: string - int

Ejemplo #5 Antes de PHP 8, +, - y . tenían la misma precedencia

<?php
$x
= 4;
// Esta línea puede causar una salida inesperada :
echo "x menos uno es igual a" . $x-1 . ", en todo caso espero\n";

// porque es evaluada como la línea siguiente (anterior a PHP 8.0.0) :
echo (("x menos uno es igual a" . $x) - 1) . ", en todo caso espero\n";

// la precedencia deseada puede ser reforzada utilizando parentesis. :
echo "x menos uno es igual a" . ($x-1) . ", en todo caso espero\n";

?>

El resultado del ejemplo sería:

-1, en todo caso espero
-1, en todo caso espero
x menos uno es igual 3, en todo caso espero

Nota:

Aunque = tiene prioridad sobre la mayoría de los operadores, PHP ejecutará expresiones como: if (!$a = foo()). En esta situación, el resultado de foo() será colocado en la variable $a.

Historial de cambios

Versión Descripción
8.0.0 La concatenación de strings (.) ahora tiene una precedencia más baja que la suma/resta aritmética (+ y -) y los desplazamientos bit a bit izquierda/derecha (<< y >>); anteriormente, esto tenía la misma precedencia que + y -, y una precedencia más alta que << y >>.
8.0.0 El operador ternario (? :) ahora es no asociativo; anteriormente, era asociativo por la izquierda.
7.4.0 Dependencia de la precedencia de la concatenación de strings (.) relativo a la suma/resta aritmética (+ o -) o los desplazamientos bit a bit izquierda/derecha (<< o >>), es decir, su uso conjunto en una expresión sin parentesis, está obsoleto.
7.4.0 Dependencia de la asociatividad por la izquierda del operador ternario (? :), es decir, la imbricación de múltiples operadores ternarios que no están entre parentesis, está obsoleta.
add a note

User Contributed Notes 8 notes

up
241
fabmlk
9 years ago
Watch out for the difference of priority between 'and vs &&' or '|| vs or':
<?php
$bool
= true && false;
var_dump($bool); // false, that's expected

$bool = true and false;
var_dump($bool); // true, ouch!
?>
Because 'and/or' have lower priority than '=' but '||/&&' have higher.
up
48
aaronw at catalyst dot net dot nz
7 years ago
If you've come here looking for a full list of PHP operators, take note that the table here is *not* complete. There are some additional operators (or operator-ish punctuation tokens) that are not included here, such as "->", "::", and "...".

For a really comprehensive list, take a look at the "List of Parser Tokens" page: http://php.net/manual/en/tokens.php
up
8
rvwoens at gmail dot com
2 years ago
Note that ?? has a low priority, so this can lead to unexpected results:

$a=[];
$a['aa']??'not set'
--> not set (as expected)

but
"lets see if it is set".$a['aa']??'not set'
--> notice; undefined index aa
--> lets see if it is set

so you need to use parenthesis
"lets see if it is set".($a['aa']??'not set')
up
53
Carsten Milkau
12 years ago
Beware the unusual order of bit-wise operators and comparison operators, this has often lead to bugs in my experience. For instance:

<?php if ( $flags & MASK == 1) do_something(); ?>

will not do what you might expect from other languages. Use

<?php if (($flags & MASK) == 1) do_something(); ?>

in PHP instead.
up
6
tlili dot mokhtar at gmail dot com
3 years ago
An easy trick to get the result of the left shift operation (<<), e.g.

15 << 2 = 15 * (2*2) = 60

15 << 3 = 15 * (2*2*2) = 120

15 << 5 = 15 * (2*2*2*2*2) = 480

and so on...

So it's:

(number on left) multiplied by (number on right) times 2.

The same goes for the right shift operator (>>), where:

(number on left) divided by (number on right) times 2 e.g.

15 >> 2 = (15/2)/2 = 7/2 = 3 (use floor values if result is in decimals).

35 >> 3 = (((35/2)/2)/2 = (17/2)/2 = 8/2 = 4
up
5
sangala at seznam dot cz
2 years ago
Using cast and ternary operator can be unclear,
(Useful to know with: declare(strict_types = 1) ).
<?php
$num_str
="5";

$i1 = (int) isset($num_str) ? $num_str : 0;
$i2 = (int) (isset($num_str) ? $num_str : 0);
var_dump($i1);
var_dump($i2);
?>
Output:
string(1) "5"
int(5)
up
12
ivan at dilber dot info
8 years ago
<?php
// Another tricky thing here is using && or || with ternary ?:
$x && $y ? $a : $b; // ($x && $y) ? $a : $b;

// while:
$x and $y ? $a : $b; // $x and ($y ? $a : $b);

?>
up
2
instatiendaweb at gmail dot com
4 years ago
//incorrect
$a = true ? 0 : true ? 1 : 2; // (true ? 0 : true) ? 1 : 2 = 2
//Unparenthesized `a ? b : c ? d : e` is not supported. Use either `(a ? b : c) ? d : e` or `a ? b : (c ? d : e)`
//correct
$a = (true ? 0 : true) ? 1 : 2; // (true ? 0 : true) ? 1 : 2 = 2

==> correction documentation.
To Top