Balping
¿Alguien puede explicar las diferencias entre taquigrafía del operador ternario (?:
) y operador coalescente nulo (??
) en PHP?
¿Cuándo se comportan de manera diferente y cuándo de la misma manera (si eso sucede)?
$a ?: $b
VS.
$a ?? $b
maestroodin
Cuando su primer argumento es nulo, son básicamente iguales excepto que la fusión nula no generará un E_NOTICE
cuando tienes una variable indefinida. El Documentos de migración de PHP 7.0 tiene esto que decir:
El operador coalescente nulo (??) se ha agregado como azúcar sintáctico para el caso común de necesitar usar un ternario junto con isset(). Devuelve su primer operando si existe y no es NULL; de lo contrario, devuelve su segundo operando.
Aquí hay un código de ejemplo para demostrar esto:
<?php
$a = null;
print $a ?? 'b'; // b
print "\n";
print $a ?: 'b'; // b
print "\n";
print $c ?? 'a'; // a
print "\n";
print $c ?: 'a'; // Notice: Undefined variable: c in /in/apAIb on line 14
print "\n";
$b = array('a' => null);
print $b['a'] ?? 'd'; // d
print "\n";
print $b['a'] ?: 'd'; // d
print "\n";
print $b['c'] ?? 'e'; // e
print "\n";
print $b['c'] ?: 'e'; // Notice: Undefined index: c in /in/apAIb on line 33
print "\n";
Las líneas que tienen el aviso son aquellas en las que estoy usando el operador ternario abreviado en lugar del operador coalescente nulo. Sin embargo, incluso con el aviso, PHP devolverá la misma respuesta.
Ejecuta el código: https://3v4l.org/McavC
Por supuesto, esto siempre es asumiendo que el primer argumento es null
. Una vez que ya no es nulo, terminas con diferencias en que el ??
operador siempre devolvería el primer argumento mientras que el ?:
taquigrafía solo lo haría si el primer argumento fuera verdadero, y eso depende de cómo PHP tipificaría las cosas a un valor booleano.
Entonces:
$a = false ?? 'f'; // false
$b = false ?: 'g'; // 'g'
entonces tendría $a
ser igual a false
y $b
igual a 'g'
.
-
Consejo: si ha estado usando ?? en lugar de ?: pero luego necesita hacer que su código sea compatible con versiones de PHP anteriores a la 7 (para un complemento, por ejemplo), entonces es posible que desee cambiar el ?? con isset($algo) ? $algo: $algo_más en todas partes de su código. Puede hacer esto fácilmente con Notepad++ o nedit (y otros editores también) usando la herramienta de buscar/reemplazar, seleccionando la opción de expresión regular e insertando en el campo de búsqueda: “\s*(\S+)\s*\?\?” y en el campo de reemplazo: ” isset($1) ? $1 :” sin las comillas (nedit usa \1 en lugar de $1). Luego reemplace todo.
– Damián Verde
8 de julio de 2017 a las 23:51
-
Esta es la respuesta correcta, sin embargo, la verificación de la veracidad es la principal diferencia y debe enfatizarse más.
– Mancze
1 de agosto de 2017 a las 12:37
-
@MasterOdin No satisfecho con su respuesta. Ambos no son iguales. Tener un resultado diferente.
– Dhairya Lakhera
18 de noviembre de 2017 a las 8:10
-
Vale la pena señalar que puedes usar ?? con encadenamiento. Por ejemplo:
$b = []; var_dump($b['a']['b']['c'] ?? 'default');
o con objetos$b = new Foo; var_dump($b->a()->b()->c() ?? 'default');
– Jack B.
6 de noviembre de 2019 a las 14:59
-
Tenga en cuenta que el comportamiento también es diferente con
$a = [];
. Ver: 3v4l.org/iCCa0– Soullivaneuh
4 de mayo de 2020 a las 14:36
a20
Ejecuté lo siguiente en el modo interactivo de php (php -a
en la terminal). El comentario en cada línea muestra el resultado.
var_export (false ?? 'value2'); // false
var_export (true ?? 'value2'); // true
var_export (null ?? 'value2'); // value2
var_export ('' ?? 'value2'); // ""
var_export (0 ?? 'value2'); // 0
var_export (false ?: 'value2'); // value2
var_export (true ?: 'value2'); // true
var_export (null ?: 'value2'); // value2
var_export ('' ?: 'value2'); // value2
var_export (0 ?: 'value2'); // value2
El operador coalescente nulo ??
??
es como una “puerta” que solo deja pasar NULL.- Entonces, siempre devuelve el primer parámetroa menos que el primer parámetro pasa a ser
NULL
. - Esto significa
??
es igual que( !isset() || is_null() )
Uso de ??
- acortar
!isset() || is_null()
controlar - p.ej
$object = $object ?? new objClassName();
Operador coalesce nulo de apilamiento
$v = $x ?? $y ?? $z;
// This is a sequence of "SET && NOT NULL"s:
if( $x && !is_null($x) ){
return $x;
} else if( $y && !is_null($y) ){
return $y;
} else {
return $z;
}
El operador ternario ?:
?:
es como una puerta que dejaanything falsy
a través de – incluyendoNULL
- Cualquier cosa falsa:
0
,empty string
,NULL
,false
,!isset()
,empty()
- Igual que el antiguo operador ternario:
X ? Y : Z
- Nota:
?:
tiraráPHP NOTICE
en indefinido (unset
o!isset()
) variables
Uso de ?:
- comprobación
empty()
,!isset()
,is_null()
etc. - acortar la operación ternaria como
!empty($x) ? $x : $y
a$x ?: $y
- acortar
if(!$x) { echo $x; } else { echo $y; }
aecho $x ?: $y
Operador ternario de apilamiento
echo 0 ?: 1 ?: 2 ?: 3; //1
echo 1 ?: 0 ?: 3 ?: 2; //1
echo 2 ?: 1 ?: 0 ?: 3; //2
echo 3 ?: 2 ?: 1 ?: 0; //3
echo 0 ?: 1 ?: 2 ?: 3; //1
echo 0 ?: 0 ?: 2 ?: 3; //2
echo 0 ?: 0 ?: 0 ?: 3; //3
// Source & Credit: http://php.net/manual/en/language.operators.comparison.php#95997
// This is basically a sequence of:
if( truthy ) {}
else if(truthy ) {}
else if(truthy ) {}
..
else {}
Apilando ambos, podemos acortar esto:
if( isset($_GET['name']) && !is_null($_GET['name'])) {
$name = $_GET['name'];
} else if( !empty($user_name) ) {
$name = $user_name;
} else {
$name="anonymous";
}
A esto:
$name = $_GET['name'] ?? $user_name ?: 'anonymous';
¿Guay, verdad? 🙂
-
Superior, excepto por un error: acortar
if(!$x) { echo $x; } else { echo $y; }
aecho $x ?: $y
. Uno no es igual al otro. La condición tiene que serif($x)
en cambio, sin negación. Todavía me ha permitido aprender un poco sobre este operador que era nuevo para mí en su versión corta, por lo que la publicación recibió un voto a favor.– Saqueador de almas
25 de noviembre de 2020 a las 12:13
-
En php, utilice siempre
elseif
como una sola palabra para alinearse con los estándares de codificación PSR-12. Sé que solo estabas haciendo una demostración, peroisset($_GET['name']) && !is_null($_GET['name'])
en primer lugar es la verificación redundante.– mickmackusa
25 de diciembre de 2020 a las 7:40
-
Esta es una muy buena respuesta para aprender cómo funcionan estos operadores, ¡pero espero nunca tener que solucionar problemas con el código de producción que usa ambos operadores en una declaración!
– Liam
12 mayo 2021 a las 19:18
Andrés
Si usa el operador ternario abreviado de esta manera, generará un aviso si $_GET['username']
no está configurado:
$val = $_GET['username'] ?: 'default';
Así que en su lugar tienes que hacer algo como esto:
$val = isset($_GET['username']) ? $_GET['username'] : 'default';
El operador coalescente nulo es equivalente a la declaración anterior, y devolverá ‘predeterminado’ si $_GET['username']
no está configurado o está null
:
$val = $_GET['username'] ?? 'default';
Tenga en cuenta que no comprueba la veracidad. Comprueba solo si está establecido y no es nulo.
También puedes hacer esto, y lo primero definido (establecido y no null
) se devolverá el valor:
$val = $input1 ?? $input2 ?? $input3 ?? 'default';
Ahora que es un operador coalescente adecuado.
-
Para que no se genere un aviso, se debe utilizar
$var = empty($other_var) ? 'default_value' : $other_var;
. Tenga en cuenta que esto excluye''
,null
,false
y0
– St3an
9 de julio de 2021 a las 13:50
Dhairya Lakhera
La gran diferencia es que
-
Operador Ternario expresión
expr1 ?: expr3
devolucionesexpr1
siexpr1
evalúa a
TRUE
pero en la otra mano Operador coalescente nulo expresión(expr1) ?? (expr2)
evalúa aexpr1
siexpr1
es noNULL
-
Operador Ternario
expr1 ?: expr3
emitir un aviso si el valor del lado izquierdo(expr1)
no existe pero por otro lado Operador coalescente nulo(expr1) ?? (expr2)
En particular, no emite un aviso si el valor del lado izquierdo(expr1)
no existe, al igual queisset()
. -
Operador Ternario se deja asociativo
((true ? 'true' : false) ? 't' : 'f');
Operador coalescente nulo es asociativo correcto
($a ?? ($b ?? $c));
Ahora vamos a explicar la diferencia entre por ejemplo:
Operador Ternario (?:)
$x='';
$value=($x)?:'default';
var_dump($value);
// The above is identical to this if/else statement
if($x){
$value=$x;
}
else{
$value="default";
}
var_dump($value);
Operador coalescente nulo (??)
$value=($x)??'default';
var_dump($value);
// The above is identical to this if/else statement
if(isset($x)){
$value=$x;
}
else{
$value="default";
}
var_dump($value);
Aquí está la tabla que explica la diferencia y similitud entre '??'
y ?:
Nota especial: el operador coalescente nulo y el operador ternario es una expresión, y no se evalúa como una variable, sino como el resultado de una expresión. Es importante saber esto si desea devolver una variable por referencia. La instrucción devuelve $foo ?? $barra; y devolver $var == 42? $a : $b; en una función de devolución por referencia, por lo tanto, no funcionará y se emitirá una advertencia.
chazy chaz
Ambos se comportan de manera diferente cuando se trata del manejo dinámico de datos.
Si la variable está vacía ( ” ), la fusión nula tratará la variable como verdadera, pero el operador ternario abreviado no lo hará. Y eso es algo a tener en cuenta.
$a = NULL;
$c="";
print $a ?? '1b';
print "\n";
print $a ?: '2b';
print "\n";
print $c ?? '1d';
print "\n";
print $c ?: '2d';
print "\n";
print $e ?? '1f';
print "\n";
print $e ?: '2f';
Y la salida:
1b
2b
2d
1f
Notice: Undefined variable: e in /in/ZBAa1 on line 21
2f
Enlace: https://3v4l.org/ZBAa1
-
Esto es claramente contrario a la intuición de PHP, donde una cadena vacía generalmente se considera falsa. Sin embargo, está claramente indicado en los documentos para ??:
It returns its first operand if it exists and is not NULL; otherwise it returns its second operand
.– Simón
17 oct 2019 a las 13:06
odio
Ambos son abreviaturas de expresiones más largas.
?:
es corto para $a ? $a : $b
. Esta expresión se evaluará como $a si $a se evalúa como VERDADERO.
??
es corto para isset($a) ? $a : $b
. Esta expresión se evaluará como $a si se establece $a y no es nulo.
Sus casos de uso se superponen cuando $a no está definido o es nulo. Cuando $a no está definido ??
no producirá un E_NOTICE, pero los resultados son los mismos. Cuando $a es nulo, el resultado es el mismo.
-
Esto es claramente contrario a la intuición de PHP, donde una cadena vacía generalmente se considera falsa. Sin embargo, está claramente indicado en los documentos para ??:
It returns its first operand if it exists and is not NULL; otherwise it returns its second operand
.– Simón
17 oct 2019 a las 13:06
Para los principiantes:
Operador coalescente nulo (??)
Todo es verdad excepto null
valores e indefinidos (variable/índice de matriz/atributos de objeto)
ex:
$array = [];
$object = new stdClass();
var_export (false ?? 'second'); # false
var_export (true ?? 'second'); # true
var_export (null ?? 'second'); # 'second'
var_export ('' ?? 'second'); # ""
var_export ('some text' ?? 'second'); # "some text"
var_export (0 ?? 'second'); # 0
var_export ($undefinedVarible ?? 'second'); # "second"
var_export ($array['undefined_index'] ?? 'second'); # "second"
var_export ($object->undefinedAttribute ?? 'second'); # "second"
esto es básicamente verificar que la variable (índice de matriz, atributo de objeto, etc.) exista y no null
. Similar a isset
función
Taquigrafía del operador ternario (?:)
todas las cosas falsas (false
,null
,0
,cadena vacía) vienen como falsos, pero si es indefinido también vienen como falsos pero Notice
tirará
ex
$array = [];
$object = new stdClass();
var_export (false ?: 'second'); # "second"
var_export (true ?: 'second'); # true
var_export (null ?: 'second'); # "second"
var_export ('' ?: 'second'); # "second"
var_export ('some text' ?? 'second'); # "some text"
var_export (0 ?: 'second'); # "second"
var_export ($undefinedVarible ?: 'second'); # "second" Notice: Undefined variable: ..
var_export ($array['undefined_index'] ?: 'second'); # "second" Notice: Undefined index: ..
var_export ($object->undefinedAttribute ?: 'second'); # "Notice: Undefined index: ..
Espero que esto ayude
Una buena manera de probarlo es usar una consola php en modo interactivo (
php -a
). Entoncesini_set('error_reporting', 'E_ALL')
yini_set('display_errors', 'on')
. Entonces puedes intentarvar_dump($var ?? 'default'))
por ejemplo, y vea qué sucede si establece cualquier tipo de valores antes– St3an
9 de julio de 2021 a las 13:55
No es fácil de encontrar a través de Google: documentación: Es posible omitir la parte media del operador ternario. Expresión
expr1 ?: expr3
devolucionesexpr1
siexpr1
evalúa atrue
yexpr3
de lo contrario.– Basj
1 de diciembre de 2021 a las 14:07