PHP üçlü operatör vs null birleştirici operatör


342

Birisi PHP'de üçlü operatör shorthand ( ?:) ve null birleştirme operatörü ( ??) arasındaki farkları açıklayabilir mi?

Ne zaman farklı davranıyorlar ve aynı şekilde ne zaman davranıyorlar?

$a ?: $b

VS.

$a ?? $b

Yanıtlar:


345

İlk argümanınız null E_NOTICEolduğunda, tanımlanmamış bir değişkeniniz olduğunda null birleştirmenin bir çıktı vermemesi dışında temel olarak aynıdırlar . PHP 7.0 göç dokümanlar bunu söylemek etti:

Boş birleştirme operatörü (??), yaygın olarak isset () ile birlikte üçlü kullanılması gerektiğinde sözdizimsel şeker olarak eklenmiştir. Varsa ve NULL değilse ilk işlenenini döndürür; aksi takdirde ikinci işlenişini döndürür.

İşte bunu göstermek için bazı örnek kod:

<?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";

Dikkatli olan satırlar, boş birleştirici operatörün aksine steno üçlü operatörü kullandığım hatlardır. Ancak, bildirimde bile, PHP aynı yanıtı geri verecektir.

Kodu yürütün: https://3v4l.org/McavC

Tabii ki, bu her zaman ilk argümanın olduğu varsayılmaktadır null. Artık null olmadığında, ??operatörün her zaman ilk argümanı döndüreceği, ancak ?:kısayolun sadece ilk argüman doğruysa alacağı ve PHP'nin bir boole'ye nasıl şeyler yazacağına bağlı olduğu farkları ile sonuçlanırsınız .

Yani:

$a = false ?? 'f'; // false
$b = false ?: 'g'; // 'g'

o $azaman eşit falseve $beşit olacaktır 'g'.


8
İpucu: kullanıyorsanız ?? yerine?: ama sonra kodunuzu 7'den eski PHP sürümleri ile uyumlu hale getirmek için kendinizi bulmak gerekir (ex için bir eklenti için), o zaman takas isteyebilirsiniz ?? isset ile ($ bir şey)? $ bir şey: kodunuzdaki her yerde $ bir şey. Bunu notepad ++ veya nedit (ve diğer editörler) ile bul / değiştir aracını kullanarak, normal ifade seçeneğini belirleyip bul alanına ekleyerek kolayca yapabilirsiniz: "\ s * (\ S +) \ s * \? \?" ve replace alanında: "isset ($ 1)? $ 1:" tırnak işaretleri olmadan (nedit $ 1 yerine \ 1 kullanır). Sonra hepsini değiştirin.
Damian Green

14
Bu doğru cevaptır, ancak doğruluk kontrolü en büyük farklılıktır ve daha fazla vurgulanmalıdır.
mancze

2
@MasterOdin Cevabınızdan memnun değil. Her ikisi de aynı değil. Farklı sonuç alın.
Meraklı

1
Kullanabileceğinizi belirtmek gerekir ?? zincirleme. Örneğin: $b = []; var_dump($b['a']['b']['c'] ?? 'default');veya nesnelerle$b = new Foo; var_dump($b->a()->b()->c() ?? 'default');
Jack B

Lütfen davranışın da farklı olduğunu unutmayın $a = [];. Bakınız: 3v4l.org/iCCa0
Soullivaneuh

75

Aşağıdaki php interaktif modda koştu ( php -aterminalde). Her satırdaki yorum sonucu gösterir.

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"

Bu benim yorumum:

1. Boş Birleştirme Operatörü - ??:

  • ??sadece NULL girmesine izin veren bir "geçit" gibidir .
  • Yani, her zaman birinci parametreyi döndürür sürece, birinci parametre olurNULL .
  • Bu araçlar ??aynı( !isset() || is_null() )

2. Üçlü Operatör - ?:

  • ?:anything falsyiçeri girmeyi sağlayan bir kapı gibidir -NULL
  • 0, empty string, NULL, false, !isset(), empty().. falsy kokuyor şey
  • Tıpkı klasik üçlü operatör gibi: echo ($x ? $x : false)
  • NOT: tanımsız ( veya ) değişkenleri ?:atarPHP NOTICEunset!isset()

3. Doktor, ne zaman kullanırım ??ve ?:..

  • Sadece şaka yapıyorum - doktor değilim ve bu sadece bir yorum
  • Ne ?:zaman kullanırdım
    • yapıyor empty($x)kontrolleri
    • Klasik üçlü operasyon gibi !empty($x) ? $x : $ykısaltılabilir$x ?: $y
    • if(!$x) { fn($x); } else { fn($y); } kısaltılabilir fn(($x ?: $y))
  • Ne ??zaman kullanırdım
    • Bir !isset() || is_null()çek yapmak istiyorum
    • örneğin bir nesnenin var olup olmadığını kontrol edin - $object = $object ?? new objClassName();

4. İstifleme operatörleri ...

  1. Üçlü Operatör istiflenebilir ...

    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

    Bu kod için kaynak ve kredi

    Bu temelde bir dizi:

    if( truthy ) {}
    else if(truthy ) {}
    else if(truthy ) {}
    ..
    else {}
  2. Null Coalese Operatörü istiflenebilir ...

    $v = $x ?? $y ?? $z; 

    Bu bir dizi:

    if(!isset($x) || is_null($x) ) {} 
    else if(!isset($y) || is_null($y) ) {}
    else {}
  3. İstifleme kullanarak, bunu kısaltabilirim:

    if(!isset($_GET['name'])){
       if($user_name){
          $name = $user_name;
       }else {
          $name = 'anonymous';
       }
    } else { 
       $name = $_GET['name'];
    }

    Buna:

    $name = $_GET['name'] ?? $user_name ?: 'anonymous';

    Güzel, değil mi? :-)


3
Açık ara en iyi cevap
Faizan Anwer Ali Rupani

69

Bu şekilde kısayol üçlü operatörünü kullanırsanız, $_GET['username']ayarlanmamışsa bir bildirime neden olur :

$val = $_GET['username'] ?: 'default';

Bunun yerine böyle bir şey yapmalısınız:

$val = isset($_GET['username']) ? $_GET['username'] : 'default';

Boş birleştirici operatörü yukarıdaki açıklamaya eşdeğerdir ve eğer 'varsayılan' dönecektir $_GET['username']set veya değil null:

$val = $_GET['username'] ?? 'default';

O Not bunu truthiness kontrol etmez . Yalnızca ayarlı olup olmadığını kontrol eder ve boş değil.

Bunu da yapabilirsiniz; ilk tanımlı (ayarlanmış ve ayarlanmamış null) değer döndürülür:

$val = $input1 ?? $input2 ?? $input3 ?? 'default';

Şimdi bu uygun bir birleştirme operatörü.


42

En büyük fark şu ki

  1. Üçlü Operatör ifade expr1 ?: expr3döner expr1eğer expr1üzere değerlendirir TRUEama diğer taraftan null Birleştirme Operatörü ifade (expr1) ?? (expr2) değerlendirir için expr1eğer expr1olduğunu değil NULL

  2. Üçlü Operatör expr1 ?: expr3 , sol taraftaki değer (expr1) yoksa, ancak diğer taraftan Boş Birleştirme Operatörü (expr1) ?? (expr2) Özellikle, sol taraftaki değer (expr1) yoksa, tıpkı bir sol taraftaki değer mevcut değilse, bir bildirim yayınlamazisset() .

  3. TernaryOperator ilişkisel kaldı

    ((true ? 'true' : false) ? 't' : 'f');

    Null Birleştirme Operatörü doğru ilişkilendirici

    ($a ?? ($b ?? $c));

Şimdi arasındaki farkı örnekle açıklayalım:

Üçlü operatör (?:)

$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);

Boş Birleştirme Operatörü (??)

$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);

İşte arasındaki farkı ve benzerliği açıklamak tablodur '??'ve?:

resim açıklamasını buraya girin

Özel Not: null birleştirme operatörü ve üçlü operatör bir ifadedir ve bir değişken için değil, bir ifadenin sonucu olarak değerlendirilir. Bir değişkeni başvuru ile döndürmek isteyip istemediğinizi bilmek önemlidir. İfade $ foo döner ?? bar, $; ve $ var == 42? $ a: $ b; referansla geri dönüş işlevinde bu nedenle çalışmaz ve bir uyarı verilir.


15

Dinamik veri işleme söz konusu olduğunda her ikisi de farklı davranır.

Değişken boşsa ('') boş birleşim, değişkeni true olarak kabul eder, ancak stenografi üçlü operatörü işlemez. Ve bu akılda tutulması gereken bir şey.

$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';

Ve çıktı:

1b
2b

2d
1f

Notice: Undefined variable: e in /in/ZBAa1 on line 21
2f

Bağlantı: https://3v4l.org/ZBAa1


Bu, boş bir dizenin genellikle yanlış kabul edildiği PHP için açıkça sezgiseldir. Yine de, dokümanlar için ??: It returns its first operand if it exists and is not NULL; otherwise it returns its second operand.
Simon

12

Her ikisi de daha uzun ifadeler için kısayollardır.

?:için kısadır $a ? $a : $b. $ A, TRUE olarak değerlendirilirse, bu ifade $ a olarak değerlendirilir .

??için kısadır isset($a) ? $a : $b. $ A ayarlanmışsa ve null değilse bu ifade $ a olarak değerlendirilir.

$ A tanımsız veya null olduğunda kullanım durumları çakışır. $ A tanımsız olduğunda ??bir E_NOTICE oluşturmaz, ancak sonuçlar aynıdır. $ A null olduğunda sonuç aynıdır.


5

Yeni başlayanlar için:

Boş birleştirme operatörü (??)

nullDeğerler ve tanımsız (değişken / dizi dizini / nesne öznitelikleri) dışında her şey doğrudur

örn:

$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"

bu temelde değişkeni (dizi indeksi, nesne özniteliği vb.) var olup olmadığını kontrol eder null. issetişleve benzer

Üçlü operatör kısaltması (? :)

Her yanlış şeyler ( false, null, 0, boş dize) Yanlış olarak gelip, ancak o tanımsız eğer o da yanlış olarak geliyor ama Noticeatacağım

eski

$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: ..

Bu yardımcı olur umarım


4

Bu bağlantıda aşağı kaydırın ve bölümü görüntüleyin, aşağıda görüldüğü gibi size karşılaştırmalı bir örnek verir:

<?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';
?>

Ancak, daha sonra okurken kodu anlamayı zorlaştırdığı için operatörleri zincirlemeniz önerilmez.

Boş birleştirme operatörü (??), yaygın olarak isset () ile birlikte üçlü kullanılması gerektiğinde sözdizimsel şeker olarak eklenmiştir. Varsa ve NULL değilse ilk işlenenini döndürür; aksi takdirde ikinci işlenişini döndürür.

Esas olarak, birleştirme operatörünün kullanılması üçlü operatörden farklı olarak otomatik olarak null olup olmadığını kontrol edecektir.


1
Lütfen zincirleme yapmayı düşünmeyin ... zincirlenmiş üçlüler gibi okumak / anlamak zor
Mark Baker

7
@MarkBaker Zincirli üçlüleri anlamak zordur çünkü PHP üçlü ilişkiyi bozmuştur. Bu, birleştirme operatörü için geçerli değildir ve imho zincirleme birleştirme mükemmel bir şekilde anlaşılabilir.
NikiC

7
Katılmıyorum. Boş birleşimi zincirlemek harika bir özelliktir ve operatörü anlarsanız okumayı zorlaştırmaz. Genellikle javascript kullanılır ve insanlar PHP ile rahat olsun kez bu zincirleme kullanmamak için çağrı durmalıdır. Üçlü zincirleri okumak çok zordur, ancak sıfır birleşmesi kolaydır. Soldan sağa okudukça, bir sonraki adımda hangi değerin kullanılması gerektiğini listeler.
earl3s

2
a || b || cPHP'nin booleans için kullanılabilmesi dışında false || 2false ?? 2
JS'deki

1
Zincirleme kullanmama konusunda size ve diğerlerine katılmıyorum. Bu, döngüler için hiç kullanmadığını söylemek gibidir, çünkü onları anlamayabilir. Geliştiriciler / kodlayıcılar, diğerleri bilmeseler bile, anladıkları kodlama standartlarını ve uygulamalarını kullanmakta tamamen özgürdür. Şahsen, zincirleme birleşmeyi anahtar ifadelere çok benziyorum. Bulunan ilk değeri (set) ve hiçbir şey bulunmazsa son değeri döndürür.
kurdtpage

3

Diğer cevaplar derinleşiyor ve harika açıklamalar veriyor. Hızlı cevap arayanlar için,

$a ?: 'fallback' dır-dir $a ? $a : 'fallback'

süre

$a ?? 'fallback' dır-dir $a = isset($a) ? $a : 'fallback'


Temel fark, sol operatör şunlardan biri olduğunda olabilir:

  • Boş DEĞİLDİR bir falsy değeri ( 0, '', false, [], ...)
  • Tanımlanmamış bir değişken

$a =Yukarıdaki genişlemede hayır olmamalıdır ??. $a ?? 'fallback' gelmez ayarlamak veya $ a değerini değiştirin. (Yalnızca bir değer döndürür).
Doin

2

Ya ??da kullanmanın artıları ve eksileri var gibi görünüyor ?:. Pro yanlısı ?:yanlış ve null ve "" aynı değerlendirir olmasıdır. Con, önceki bağımsız değişken boşsa bir E_NOTICE bildirmesidir. İle ??pro hiçbir E_NOTICE olduğunu, ancak aleyhte aynı yanlış ve boş değerlendirmek olmamasıdır. Benim tecrübelerime göre, insanlar null ve false ifadelerini birbirinin yerine kullanmaya başladığını gördüm, ancak sonunda kodlarını null veya false kullanarak tutarlı olacak şekilde değiştirmeye başvuruyorlar, ancak her ikisini birden değil. Bir alternatif daha ayrıntılı üçlü koşul oluşturmaktır: (isset($something) or !$something) ? $something : $something_else.

Aşağıda, ??hem null hem de false kullanarak işleci kullanma farkına bir örnek verilmiştir :

$false = null;
$var = $false ?? "true";
echo $var . "---<br>";//returns: true---

$false = false;
$var = $false ?? "true";
echo $var . "---<br>"; //returns: ---

Ancak üçlü operatör üzerinde durularak, yanlış veya boş bir dize "", bir e_notice atmadan boşmuş gibi davranabiliriz:

$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---

Şahsen, PHP'nin gelecekteki bir rev başka bir yeni operatör içeriyorsa gerçekten güzel olacağını düşünüyorum: :?bu yukarıdaki sözdiziminin yerini aldı. ie: // $var = $false :? "true";Bu sözdizimi null, false ve "" eşit olarak değerlendirilir ve E_NOTICE atmaz ...


3
$ var = $ false kullanabilirsiniz ?? null?: "Dize boş / false / null / undefined";
RedSparr0w

Vay ... ?? null ?:şey çok güzel, teşekkürler bayım. akıllı adam.
Blaine Lafreniere

1
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.

0

Null Coalescing operatorsadece iki görevi yerine getirir: denetler whether the variable is setve whether it is null. Aşağıdaki örneğe bir göz atın:

<?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'

Yukarıdaki kod örneği Null Coalescing operator, var olmayan bir değişkeni NULLve aynı şekilde ayarlanmış bir değişkeni ele aldığını belirtir .

Null Coalescing operatorüzerinde bir gelişme ternary operator. İkisini karşılaştıran aşağıdaki kod snippet'ine bir göz atın:

<?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.

Bu nedenle, ikisi arasındaki fark, Null Coalescing operatoroperatörün tanımlanmamış değişkenleri ternary operator. Oysa bunun ternary operatoriçin bir kısayol if-else.

Null Coalescing operatoryerine geçmesi amaçlanmamıştır ternary operator, ancak yukarıdaki örnekte olduğu gibi bazı kullanım durumlarında, daha az güçlükle temiz kod yazmanıza izin verir.

Kredi: http://dwellupper.io/post/6/php7-null-coalescing-operator-usage-and-examples


isset($_POST['fullname'])zaten NULLdeğerleri kontrol ediyor - bu yüzden && !is_null($_POST['fullname'])ilk örnekte zaten gereksiz
Yaron U.

0

$ _GET veya $ _REQUEST gibi süper küreselleri kullanırken boş bir dize olabileceğini bilmelisiniz. Bu özel durumda bu örnek

$username = $_GET['user'] ?? 'nobody';

$ username değeri artık boş bir dize olduğundan başarısız olur.

Bu yüzden $ _GET hatta $ _REQUEST kullanırken, bunun yerine üçlü operatörü kullanmalısınız:

$username = (!empty($_GET['user'])?$_GET['user']:'nobody';

Şimdi $ username değeri beklendiği gibi 'kimse' değil.


İyi yakalama. Ayrıca, boş bir dizgide birleşim operatörü de başarısız olur.
Choxx
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.