La precedencia de un operador indica qué tan "estrechamente" se unen dos
expresiones juntas. Por ejemplo, en la expresión 1 +
5 * 3
, la respuesta es 16
y no
18
porque el operador de multiplicación ("*")
tiene una precedencia mayor que el operador de adición ("+").
Los paréntesis pueden ser usados para forzar la precedencia, si es necesario. Por
ejemplo: (1 + 5) * 3
se evalúa como
18
.
Cuando los operadores tienen igual precedencia su asociatividad decide
cómo se agrupan. Por ejemplo "-" tiene asociatividad a izquierda, así
1 - 2 - 3
se agrupa como (1 - 2) - 3
y se evalúa a -4
. "=", por otra parte, tiene
asociatividad a derecha, así $a = $b = $c
se agrupa como
$a = ($b = $c)
.
Los operadores de igual precedencia que no son asociativos no pueden usarse
unos junto a otros, por ejemplo, 1 < 2 > 1
es
ilegal en PHP. La expresión 1 <= 1 == 1
, por otro
lado, es legal, ya que el operador ==
tiene menos
precedencia que el operador <=
.
Asociatividad sólo es significativa para operadores binarios (y ternarios).
Los operadores unarios son prefijos o postfijos, por lo que esta noción no es aplicable.
Por ejemplo !!$a
sólo puede agruparse como !(!$a)
.
El uso de paréntesis, incluso cuando no es estrictamente necesario, a menudo puede aumentar la legibilidad del código haciendo grupos explícitamente en lugar de confiar en la precedencia y asociatividad implícitas del operador.
La siguiente tabla enumera los operadores en orden de precedencia, con los de más alta precedencia al inicio. Los operadores en la misma línea tienen igual precedencia, en cuyo caso la asociatividad decide el agrupamiento.
Asociatividad | Operadores | Información adicional |
---|---|---|
no asociativo |
clone
new
|
clone y new |
derecha | ** |
aritmética |
no asociativo |
+
-
++
--
~
(int)
(float)
(string)
(array)
(object)
(bool)
@
|
aritmética (unarios + y - ),
incremento/disminución,
bit a bit,
conversión de tipos y
control de errores
|
izquierda | instanceof |
tipos |
no asociativo | ! |
lógico |
izquierda |
*
/
%
|
aritmética |
izquierda |
+
-
.
|
aritmética (binarios + y - ),
array y
string (. antes de PHP 8.0.0)
|
izquierda |
<<
>>
|
bit a bit |
izquierda | . |
string (desde PHP 8.0.0) |
non-associative |
<
<=
>
>=
|
comparison |
no asociativo |
==
!=
===
!==
<>
<=>
|
comparación |
izquierda | & |
bit a bit y referencias |
izquierda | ^ |
bit a bit |
izquierda | | |
bit a bit |
izquierda | && |
lógico |
izquierda | || |
lógico |
derecha | ?? |
coalescencia de nulos |
no asociativo | ? : |
ternario (asociativo a la izquierda antes de PHP 8.0.0) |
derecha |
=
+=
-=
*=
**=
/=
.=
%=
&=
|=
^=
<<=
>>=
??=
|
asignación |
no asociativo | yield from |
yield from |
no asociativo | yield |
yield |
no asociativo | 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 del operador ternario difiere de C/C++
$a = true ? 0 : true ? 1 : 2; // (true ? 0 : true) ? 1 : 2 = 2 (antes de PHP 8.0.0)
$a = 1;
$b = 2;
$a = $b += 3; // $a = ($b += 3) -> $a = 5, $b = 5
?>
La precedencia y asociatividad de los operadores solamente determinan cómo se agrupan las expresiones, no especifican un orden de evaluación. PHP no especifica (en general) el orden en que se evalúa una expresión y se debería evitar el código que se asume un orden específico de evaluación, ya que el comportamiento puede cambiar entre versiones de PHP o dependiendo de código circundante.
Ejemplo #2 Orden de evaluación no definido
<?php
$a = 1;
echo $a + $a++; // Podría imprimir 2 o 3
$i = 1;
$array[$i] = $i++; // Podría establecer el índice 1 o 2
?>
Ejemplo #3 +
, -
y .
tienen la misma precedencia (antes de PHP 8.0.0)
<?php
$x = 4;
// Esta línea podría resultar en una salida inesperada:
echo "x menos uno igual a " . $x-1 . ", o eso espero\n";
// Ya que se evalúa como esta línea:
echo (("x menos uno igual a " . $x) - 1) . ", o eso espero\n";
// La precedencia deseada se puede forzar con paréntesis:
echo "x menos uno igual a " . ($x-1) . ", o eso espero\n";
?>
El resultado del ejemplo sería:
x menos uno igual a -1, o eso espero x menos uno igual a -1, o eso espero x menos uno igual a 3, o eso espero
Nota:
Aunque
=
tiene una precedencia menor que la mayoría de los demás operadores, PHP aun permitirá expresiones similares a lo siguiente:if (!$a = foo())
, en cuyo caso el valor devuelto defoo()
es puesto en $a.
Versión | Descripción |
---|---|
8.0.0 |
La concatenación de cadenas (. ) ahora tiene una precedencia menor que
la suma/resta aritmética (+ y - ) y
el desplazamiento de bits izquierda/derecha (<< y >> );
anteriormente tenía la misma precedencia que + y -
y una precedencia mayor que << y >> .
|
8.0.0 |
El operador ternario (? : ) ahora no es asociativo;
anteriormente era asociativo a la izquierda.
|
7.4.0 |
Confiando en la precendencia de la concatenación de cadenas (. )
en relación a la suma/resta aritmética (+ o - ) o
el desplazamiento de bits izquierda/derecha (<< o >> ),
es decir, usarlos juntos en una expresión sin paréntesis, está obsoleto.
|
7.4.0 |
Confiando en la asociatividad a la izquierda del operador ternario (? : ),
es decir, anidar múltiples operadores ternarios sin paréntesis, está obsoleto.
|