Respostas:
Quando seu primeiro argumento é nulo, eles são basicamente os mesmos, exceto que a coalescência nula não produzirá um E_NOTICE
quando você tiver uma variável indefinida. Os documentos de migração do PHP 7.0 têm a dizer:
O operador coalescente nulo (??) foi adicionado como açúcar sintático para o caso comum de precisar usar um ternário em conjunto com isset (). Retorna seu primeiro operando se existir e não for NULL; caso contrário, ele retornará seu segundo operando.
Aqui está um exemplo de código para demonstrar isso:
<?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";
As linhas que têm o aviso são aquelas em que estou usando o operador ternário de taquigrafia, em oposição ao operador coalescente nulo. No entanto, mesmo com o aviso, o PHP dará a mesma resposta.
Execute o código: https://3v4l.org/McavC
Claro, isso sempre está assumindo que o primeiro argumento é null
. Uma vez que não é mais nulo, você termina com diferenças em que o ??
operador sempre retornaria o primeiro argumento, enquanto a ?:
abreviação retornaria apenas se o primeiro argumento fosse verdadeiro, e isso depende de como o PHP converteria as coisas em um valor booleano .
Assim:
$a = false ?? 'f'; // false
$b = false ?: 'g'; // 'g'
seria então $a
igual false
e $b
igual a 'g'
.
$b = []; var_dump($b['a']['b']['c'] ?? 'default');
ou com objetos$b = new Foo; var_dump($b->a()->b()->c() ?? 'default');
$a = [];
. Veja: 3v4l.org/iCCa0
Execute o abaixo no modo interativo php ( php -a
no terminal). O comentário em cada linha mostra o 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"
??
:??
é como um "portão" que apenas permite a passagem de NULL .NULL
. ??
é o mesmo que( !isset() || is_null() )
?:
?:
é como um portão que deixa anything falsy
passar - incluindoNULL
0
, empty string
, NULL
, false
, !isset()
, empty()
.. qualquer coisa que cheira Falsasecho ($x ? $x : false)
?:
lançará variáveis PHP NOTICE
indefinidas ( unset
ou !isset()
)??
e ?:
..?:
quando
empty($x)
cheques!empty($x) ? $x : $y
pode ser reduzida para$x ?: $y
if(!$x) { fn($x); } else { fn($y); }
pode ser reduzido para fn(($x ?: $y))
??
quando
!isset() || is_null()
verificação$object = $object ?? new objClassName();
O operador ternário pode ser empilhado ...
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
Origem e crédito para este código
Esta é basicamente uma sequência de:
if( truthy ) {}
else if(truthy ) {}
else if(truthy ) {}
..
else {}
O operador de carvão nulo pode ser empilhado ...
$v = $x ?? $y ?? $z;
Esta é uma sequência de:
if(!isset($x) || is_null($x) ) {}
else if(!isset($y) || is_null($y) ) {}
else {}
Usando o empilhamento, posso encurtar isso:
if(!isset($_GET['name'])){
if($user_name){
$name = $user_name;
}else {
$name = 'anonymous';
}
} else {
$name = $_GET['name'];
}
Para isso:
$name = $_GET['name'] ?? $user_name ?: 'anonymous';
Legal certo? :-)
Se você usar o operador ternário de atalho como este, ele causará um aviso se $_GET['username']
não estiver definido:
$val = $_GET['username'] ?: 'default';
Então, em vez disso, você deve fazer algo assim:
$val = isset($_GET['username']) ? $_GET['username'] : 'default';
O operador coalescente nulo é equivalente à instrução acima e retornará 'padrão' se $_GET['username']
não estiver definido ou estiver null
:
$val = $_GET['username'] ?? 'default';
Observe que ele não verifica a veracidade . Ele verifica apenas se está definido e não é nulo.
Você também pode fazer isso e o primeiro valor definido (definido e não null
) será retornado:
$val = $input1 ?? $input2 ?? $input3 ?? 'default';
Agora esse é um operador coalescente adequado.
A principal diferença é que
A expressão Ternary Operatorexpr1 ?: expr3
retorna expr1
se for expr1
avaliada como,
TRUE
mas por outro lado, a expressão Null Coalescing Operator(expr1) ?? (expr2)
avalia expr1
se expr1
for não for NULL
O operador ternário expr1 ?: expr3
emite um aviso se o valor do lado esquerdo (expr1)
não existir, mas, por outro lado, operador nulo de coalescência (expr1) ?? (expr2)
Em particular, não emite um aviso se o valor do lado esquerdo (expr1)
não existir, assim como isset()
.
TernaryOperator é deixado associativo
((true ? 'true' : false) ? 't' : 'f');
O operador de coalescência nulo é associativo correto
($a ?? ($b ?? $c));
Agora vamos explicar a diferença entre por exemplo:
Operador ternário (?:)
$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 coalescência 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);
Aqui está a tabela que explica a diferença e semelhança entre '??'
e?:
Nota especial: operador coalescente nulo e operador ternário é uma expressão, e que não é avaliado para uma variável, mas para o resultado de uma expressão. É importante saber se você deseja retornar uma variável por referência. A declaração retorna $ foo ?? $ bar; e retornar $ var == 42? $ a: $ b; em uma função de retorno por referência, portanto, não funcionará e um aviso será emitido.
Ambos se comportam de maneira diferente quando se trata de manipulação dinâmica de dados.
Se a variável estiver vazia (''), a coalescência nula tratará a variável como verdadeira, mas o operador ternário abreviado não. E isso é algo a ter em mente.
$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';
E a saída:
1b
2b
2d
1f
Notice: Undefined variable: e in /in/ZBAa1 on line 21
2f
Link: https://3v4l.org/ZBAa1
It returns its first operand if it exists and is not NULL; otherwise it returns its second operand
.
Ambos são atalhos para expressões mais longas.
?:
é a abreviação de $a ? $a : $b
. Essa expressão será avaliada como $ a se $ a for avaliada como TRUE .
??
é a abreviação de isset($a) ? $a : $b
. Essa expressão será avaliada como $ a se $ a estiver definido e não nulo.
Seus casos de uso se sobrepõem quando $ a é indefinido ou nulo. Quando $ a é indefinido ??
, não produz um E_NOTICE, mas os resultados são os mesmos. Quando $ a é nulo, o resultado é o mesmo.
Para iniciantes:
Operador coalescente nulo (??)
Tudo é verdade, exceto null
valores e indefinidos (atributos de índice de variável / matriz / 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"
isso é basicamente verificar se a variável (índice do array, atributo do objeto etc.) existe e não existe null
. semelhante à isset
função
Taquigrafia do operador ternário (? :)
cada coisas falsas ( false
, null
, 0
, string vazia) são vir como falsa, mas se é um indefinido também vir como falsa, mas Notice
vai jogar
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 isto ajude
Role para baixo neste link e veja a seção, ele fornece um exemplo comparativo, como visto abaixo:
<?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';
?>
No entanto, não é aconselhável encadear os operadores, pois dificulta a compreensão do código ao lê-lo posteriormente.
O operador coalescente nulo (??) foi adicionado como açúcar sintático para o caso comum de precisar usar um ternário em conjunto com isset (). Retorna seu primeiro operando se existir e não for NULL; caso contrário, ele retornará seu segundo operando.
Essencialmente, o uso do operador coalescente tornará a verificação automática de nulo, diferente do operador ternário.
a || b || c
padrão em JS, exceto PHP do pode ser usado para booleans ( false || 2
em JS é 2; false ?? 2
em PHP é false)
As outras respostas são profundas e dão ótimas explicações. Para quem procura uma resposta rápida,
$a ?: 'fallback'
é $a ? $a : 'fallback'
enquanto
$a ?? 'fallback'
é $a = isset($a) ? $a : 'fallback'
A principal diferença seria quando o operador esquerdo é:
0
, ''
, false
, []
, ...)$a =
na expansão acima de ??
. $a ?? 'fallback'
não define nem altera o valor de $ a. (Ele apenas retorna um valor).
Parece que existem prós e contras no uso de um ??
ou outro ?:
. O profissional a usar ?:
é que ele avalia falso e nulo e "" o mesmo. O engodo é que ele relata um E_NOTICE se o argumento anterior for nulo. Com ??
o profissional, não há E_NOTICE, mas o contrário é que ele não avalia falso e nulo da mesma forma. Na minha experiência, vi pessoas começarem a usar nulo e falso de forma intercambiável, mas depois acabaram recorrendo a modificar seu código para ser consistente com o uso de nulo ou falso, mas não ambos. Uma alternativa é criar uma condição ternária mais elaborada: (isset($something) or !$something) ? $something : $something_else
.
A seguir, é apresentado um exemplo da diferença de usar o ??
operador usando null e false:
$false = null;
$var = $false ?? "true";
echo $var . "---<br>";//returns: true---
$false = false;
$var = $false ?? "true";
echo $var . "---<br>"; //returns: ---
Ao elaborar o operador ternário, no entanto, podemos fazer com que uma string "" falsa ou vazia se comporte como se fosse um nulo sem gerar um e_notice:
$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---
Pessoalmente, acho que seria muito bom se uma futura revisão do PHP incluísse outro novo operador: :?
que substituísse a sintaxe acima. ou seja:
// $var = $false :? "true";
Essa sintaxe avaliaria nulo, falso e "" igualmente e não lançaria um E_NOTICE ...
?? null ?:
coisa é incrível, obrigado Sr. cara inteligente.
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.
Null Coalescing operator
executa apenas duas tarefas: verifica whether the variable is set
e whether it is null
. Veja o seguinte exemplo:
<?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'
O exemplo de código acima afirma que Null Coalescing operator
trata uma variável inexistente e uma variável que é definida NULL
da mesma maneira.
Null Coalescing operator
é uma melhoria sobre o ternary operator
. Dê uma olhada no seguinte trecho de código comparando os dois:
<?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.
Portanto, a diferença entre os dois é que o Null Coalescing operator
operador foi projetado para lidar com variáveis indefinidas melhor que o ternary operator
. Visto que o ternary operator
é uma abreviação de if-else
.
Null Coalescing operator
não pretende substituir ternary operator
, mas em alguns casos de uso, como no exemplo acima, permite escrever código limpo com menos problemas.
Créditos: http://dwellupper.io/post/6/php7-null-coalescing-operator-usage-and-examples
isset($_POST['fullname'])
já verifica NULL
valores - portanto, && !is_null($_POST['fullname'])
no primeiro exemplo, é redundante de qualquer maneira #
Ao usar superglobais como $ _GET ou $ _REQUEST, você deve estar ciente de que eles podem ser uma sequência vazia. Neste caso especal, este exemplo
$username = $_GET['user'] ?? 'nobody';
falhará porque o valor de $ username agora é uma string vazia.
Portanto, ao usar $ _GET ou mesmo $ _REQUEST, você deve usar o operador ternário da seguinte maneira:
$username = (!empty($_GET['user'])?$_GET['user']:'nobody';
Agora, o valor de $ username é 'ninguém' conforme o esperado.