operator - php double question mark
Operador ternario PHP vs operador de fusiĆ³n nula (13)
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
¿Alguien puede explicar las diferencias entre la abreviatura del operador ternario (
?:
:) Y el operador de fusión nula (
??
) en PHP?
¿Cuándo se comportan de manera diferente y de la misma manera (si eso sucede)?
$a ?: $b
VS.
$a ?? $b
Ambos son shorthands para expresiones más largas.
?:
es corto por
$a ? $a : $b
$a ? $a : $b
.
Esta expresión se evaluará a $ a si $ a se evalúa como
VERDADERO
.
??
es la abreviatura de
isset($a) ? $a : $b
isset($a) ? $a : $b
.
Esta expresión se evaluará a $ a si $ a está establecido 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.
Cuando su primer argumento es nulo, son básicamente los mismos, excepto que la fusión nula no generará un
E_NOTICE
cuando tenga una variable indefinida.
Los
documentos de migración de PHP 7.0
tienen esto que decir:
El operador de fusión 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 de fusión nula. Sin embargo, incluso con el aviso, PHP devolverá la misma respuesta.
Ejecute el código: https://3v4l.org/McavC
Por supuesto, esto siempre supone que el primer argumento es
null
.
Una vez que ya no es nulo, entonces terminas con diferencias en que el
??
El operador siempre devolvería el primer argumento mientras que la abreviatura
?:
solo lo haría si el primer argumento fuera verdadero, y eso se basa en cómo
PHP convertiría las cosas a un valor booleano
.
Entonces:
$a = false ?? ''f''; // false
$b = false ?: ''g''; // ''g''
entonces tendría
$a
igual a
false
y
$b
igual a
''g''
.
Cuando utilice las superglobales como $ _GET o $ _REQUEST, debe tener en cuenta que podrían ser una cadena vacía. En este caso especial este ejemplo
$username = $_GET[''user''] ?? ''nobody'';
fallará porque el valor de $ username ahora es una cadena vacía.
Por lo tanto, cuando use $ _GET o incluso $ _REQUEST, debe usar el operador ternario como este:
$username = (!empty($_GET[''user''])?$_GET[''user'']:''nobody'';
Ahora el valor de $ username es ''nobody'' como se esperaba.
Desplácese hacia abajo en this enlace y vea la sección, le da un ejemplo comparativo como se ve a continuación:
$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: ..
Sin embargo, no se recomienda encadenar a los operadores ya que dificulta la comprensión del código al leerlo más adelante.
El operador de fusión 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.
Esencialmente, el uso del operador coalescente hará que la comprobación automática sea nula, a diferencia del operador ternario.
Ejecuté el siguiente en modo interactivo
php -a
(
php -a
en terminal).
El comentario en cada línea muestra el resultado.
var_dump (false ?? ''value2''); # bool(false)
var_dump (true ?? ''value2''); # bool(true)
var_dump (null ?? ''value2''); # string(6) "value2"
var_dump ('''' ?? ''value2''); # string(0) ""
var_dump (0 ?? ''value2''); # int(0)
var_dump (false ?: ''value2''); # string(6) "value2"
var_dump (true ?: ''value2''); # bool(true)
var_dump (null ?: ''value2''); # string(6) "value2"
var_dump ('''' ?: ''value2''); # string(6) "value2"
var_dump (0 ?: ''value2''); # string(6) "value2"
Entonces esta es mi interpretación:
1. El operador de fusión nula -
??
:
-
??
es como una "puerta" que solo deja pasar NULL . -
Por
lo
tanto,
siempre devuelve el primer parámetro
, a menos que el
primer parámetro sea
NULL
. -
Esto significa
??
es igual que( !isset() || is_null() )
2. El operador ternario -
?:
-
?:
es como una puerta que deja pasaranything falsy
, incluidoNULL
-
0
,empty string
,NULL
,false
!isset()
,empty()
.. cualquier cosa que huela a falso -
Al igual que el operador ternario clásico:
echo ($x ? $x : false)
-
NOTA:
?:
!isset()
PHP NOTICE
en variables indefinidas (unset
o!isset()
)
3. Entonces doctor, ¿cuándo uso
??
y
?:
..
- Solo estoy bromeando, no soy médico y esto es solo una interpretación
-
Yo usaría
?:
Cuando-
haciendo cheques
empty($x)
-
¿Operación ternaria clásica como
!empty($x) ? $x : $y
!empty($x) ? $x : $y
se puede acortar a$x ?: $y
-
if(!$x) { fn($x); } else { fn($y); }
if(!$x) { fn($x); } else { fn($y); }
se puede acortar afn(($x ?: $y))
-
haciendo cheques
-
Yo usaría
??
cuando-
Quiero hacer un
!isset() || is_null()
!isset() || is_null()
check -
por ejemplo, verificar si existe un objeto -
$object = $object ?? new objClassName();
$object = $object ?? new objClassName();
-
Quiero hacer un
4. Operadores de apilamiento ...
-
El operador ternario se puede apilar ...
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
Fuente y crédito para este código
Esto es básicamente una secuencia de:
if( truthy ) {} else if(truthy ) {} else if(truthy ) {} .. else {}
-
El operador nulo coalese se puede apilar ...
$v = $x ?? $y ?? $z;
Esta es una secuencia de:
if(!isset($x) || is_null($x) ) {} else if(!isset($y) || is_null($y) ) {} else {}
-
Usando el apilamiento, puedo acortar esto:
if(!isset($_GET[''name''])){ if(isset($user_name) && !empty($user_name)){ $name = $user_name; }else { $name = ''anonymous''; } } else { $name = $_GET[''name'']; }
A esto:
$name = $_GET[''name''] ?? $user_name ?: ''anonymous'';
¿Guay, verdad? :-)
La principal diferencia es que
-
Expresión de operador ternario
expr1 ?: expr3
devuelveexpr1
siexpr1
evalúa comoTRUE
pero, por otro lado, ¿ Expresión de operador de fusión nula(expr1) ?? (expr2)
(expr1) ?? (expr2)
evalúa comoexpr1
siexpr1
no esNULL
-
Operador ternario
expr1 ?: expr3
emite un aviso si el valor del lado izquierdo(expr1)
no existe pero, por otro lado, ¿Operador de fusión nula(expr1) ?? (expr2)
(expr1) ?? (expr2)
En particular, no emite un aviso si el valor del lado izquierdo(expr1)
no existe, al igual queisset()
. -
TernaryOperator se deja asociativo
((true ? ''true'' : false) ? ''t'' : ''f'');
El operador de fusión nula 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 de fusión nula
(??)
$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 de fusión nulo y el operador ternario es una expresión, y que no evalúa una variable, sino el resultado de una expresión. Esto es importante para saber si desea devolver una variable por referencia. La declaración devuelve $ foo ?? $ bar; y devolver $ var == 42? $ a: $ b; en una función de retorno por referencia, por lo tanto, no funcionará y se emitirá una advertencia.
Las otras respuestas son profundas y dan grandes explicaciones. Para aquellos que buscan una respuesta rápida,
$a ?: ''fallback''
es
$a ? $a : ''fallback''
$a ? $a : ''fallback''
mientras
$a ?? ''fallback''
$a ?? ''fallback''
es
$a = isset($a) ? $a : ''fallback''
$a = isset($a) ? $a : ''fallback''
La principal diferencia sería cuando el operador izquierdo es:
-
Un valor falso que NO es nulo (
0
,''''
,false
,[]
, ...) - Una variable indefinida
Para los principiantes:
Operador de fusión nula (??)
Todo es verdadero excepto valores
null
e indefinidos (variables / índice de matriz / atributos de objeto)
ex:
<?php
/** Fetches the value of $_GET[''user''] and returns ''nobody'' if it does not exist. **/
$username = $_GET[''user''] ?? ''nobody'';
/** This is equivalent to: **/
$username = isset($_GET[''user'']) ? $_GET[''user''] : ''nobody'';
/** Coalescing can be chained: this will return the first defined value out of $_GET[''user''], $_POST[''user''], and ''nobody''. **/
$username = $_GET[''user''] ?? $_POST[''user''] ?? ''nobody'';
?>
esto es básicamente verificar que la variable (índice de matriz, atributo de objeto, etc.) exista y no sea
null
.
similar a la función
isset
Taquigrafía del operador ternario (? :)
todas las cosas falsas (
false
,
null
,
0
, cadena vacía) se vuelven falsas, pero si es indefinido también se vuelven falsas, pero
Notice
arrojará
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"
Espero que esto ayude
Parece que hay ventajas y desventajas de usar cualquiera
??
o
?:
.
La ventaja de usar
?:
Es que evalúa falso y nulo y "" lo mismo.
La desventaja es que informa un E_NOTICE si el argumento anterior es nulo.
Con
??
La ventaja es que no hay E_NOTICE, pero la desventaja es que no evalúa falso y nulo.
En mi experiencia, he visto a personas comenzar a usar nulo y falso indistintamente, pero luego eventualmente recurren a modificar su código para que sea consistente con el uso de nulo o falso, pero no ambos.
Una alternativa es crear una condición ternaria más elaborada:
(isset($something) or !$something) ? $something : $something_else
(isset($something) or !$something) ? $something : $something_else
.
El siguiente es un ejemplo de la diferencia de usar el
??
operador utilizando tanto nulo como falso:
$false = null;
$var = $false ?? "true";
echo $var . "---<br>";//returns: true---
$false = false;
$var = $false ?? "true";
echo $var . "---<br>"; //returns: ---
Sin embargo, al elaborar el operador ternario, podemos hacer que una cadena "" falsa o vacía "se comporte como si fuera un valor nulo sin emitir un aviso_e:
$false = null;
$var = (isset($false) or !$false) ? $false : "true";
echo $var . "---<br>";//returns: ---
$false = false;
$var = (isset($false) or !$false) ? $false : "true";
echo $var . "---<br>";//returns: ---
$false = "";
$var = (isset($false) or !$false) ? $false : "true";
echo $var . "---<br>";//returns: ---
$false = true;
$var = (isset($false) or !$false) ? $false : "true";
echo $var . "---<br>";//returns: 1---
Personalmente, creo que sería realmente bueno si una futura revisión de PHP incluyera otro nuevo operador
:?
eso reemplazó la sintaxis anterior.
es decir:
// $var = $false :? "true";
// $var = $false :? "true";
Esa sintaxis evaluaría nulo, falso y "" por igual y no arrojaría una E_NOTICE ...
Si utiliza el operador ternario de acceso directo de esta manera, generará un aviso si
$_GET[''username'']
no está configurado:
$val = $_GET[''username''] ?: ''default'';
Entonces, en cambio, tienes que hacer algo como esto:
$val = isset($_GET[''username'']) ? $_GET[''username''] : ''default'';
El
operador de fusión nulo
es equivalente a la declaración anterior y devolverá ''default'' si
$_GET[''username'']
no está establecido o es
null
:
$val = $_GET[''username''] ?? ''default'';
Tenga en cuenta que no verifica la veracidad . Comprueba solo si está configurado y no es nulo.
También puede hacer esto, y se devolverá el primer valor
definido
(establecido y no
null
):
$val = $input1 ?? $input2 ?? $input3 ?? ''default'';
Ahora que es un operador de fusión apropiado.
Null Coalescing operator
realiza solo dos tareas: comprueba
whether the variable is set
y
whether it is null
.
Eche un vistazo al siguiente ejemplo:
<?php
# case 1:
$greeting = ''Hola'';
echo $greeting ?? ''Hi There''; # outputs: ''Hola''
# case 2:
$greeting = null;
echo $greeting ?? ''Hi There''; # outputs: ''Hi There''
# case 3:
unset($greeting);
echo $greeting ?? ''Hi There''; # outputs: ''Hi There''
El ejemplo de código anterior establece que el
Null Coalescing operator
trata una variable no existente y una variable que se establece en
NULL
de la misma manera.
Null Coalescing operator
es una mejora con respecto al
ternary operator
.
Eche un vistazo al siguiente fragmento de código que compara los dos:
<?php /* example: checking for the $_POST field that goes by the name of ''fullname''*/
# in ternary operator
echo "Welcome ", (isset($_POST[''fullname'']) && !is_null($_POST[''fullname'']) ? $_POST[''fullname''] : ''Mr. Whosoever.''); # outputs: Welcome Mr. Whosoever.
# in null coalecing operator
echo "Welcome ", ($_POST[''fullname''] ?? ''Mr. Whosoever.''); # outputs: Welcome Mr. Whosoever.
Entonces, la diferencia entre los dos es que el
Null Coalescing operator
operador de
Null Coalescing operator
está diseñado para manejar variables indefinidas mejor que el
ternary operator
.
Mientras que, el
ternary operator
es una abreviatura de
if-else
.
Null Coalescing operator
no está destinado a reemplazar al
ternary operator
, pero en algunos casos de uso, como en el ejemplo anterior, le permite escribir código limpio con menos problemas.
Créditos: http://dwellupper.io/post/6/php7-null-coalescing-operator-usage-and-examples
class a
{
public $a = ''aaa'';
}
$a = new a();
echo $a->a; // Writes ''aaa''
echo $a->b; // Notice: Undefined property: a::$b
echo $a->a ?? ''$a->a does not exists''; // Writes ''aaa''
// Does not throw an error although $a->b does not exist.
echo $a->b ?? ''$a->b does not exist.''; // Writes $a->b does not exist.
// Does not throw an error although $a->b and also $a->b->c does not exist.
echo $a->b->c ?? ''$a->b->c does not exist.''; // Writes $a->b->c does not exist.