Cara terbaik untuk memberikan variabel nilai default (mensimulasikan Perl ||, || =)

134

Saya suka melakukan hal semacam ini di Perl: $foo = $bar || $bazuntuk menetapkan $bazke $foojika $barkosong atau tidak terdefinisi. Anda juga memiliki $foo ||= $bletchyang hanya akan menetapkan $bletchuntuk $foojika $footidak didefinisikan atau kosong.

Operator ternary dalam situasi ini membosankan dan melelahkan. Tentunya ada metode sederhana dan elegan yang tersedia di PHP?

Atau satu-satunya jawaban fungsi kustom yang menggunakan isset ()?

Tom Auger
sumber
1
BTW operator Perl dengan fungsi yang diinginkan adalah //dan //=dan mereka ada pada Perl v5.10.0. Yang asli ||dan ||=uji untuk nilai logis, bukan untuk definisi.
Palec
@Palec, mengapa pertanyaan berusia 4 tahun dengan 29 upvotes dapat diidentifikasi sebagai duplikat dari pertanyaan berusia 1 tahun dengan 6 upvotes (yang itu sendiri ditandai sebagai duplikat dari pertanyaan lain?) Saya pikir ada nilai besar dalam menjaga ini pertanyaan, karena judulnya lebih umum (tidak merujuk jawaban yaitu: isset ()).
Tom Auger
Itu duplikat yang jelas dan tepat. Mengakui aku tidak terlalu memikirkan yang mana yang seharusnya menjadi yang asli, aku berada di tengah-tengah sesuatu yang lain, membuat hubungan antara keduanya adalah tujuannya. Mencabut VTC saya.
Palec
Duplikat yang tepat, ditandai (salah IMO) sebagai duplikat dari pertanyaan lain: PHP singkatan dari isset ()?
Palec

Jawaban:

130

Dalam PHP 7 kami akhirnya memiliki cara untuk melakukan ini dengan elegan. Ini disebut operator penggabungan Null . Anda bisa menggunakannya seperti ini:

$name = $_GET['name'] ?? 'john doe';

Ini setara dengan

$name = isset($_GET['name']) ? $_GET['name']:'john doe';
jpschroeder
sumber
14
Saya berpendapat operator ruang angkasa juga pantas.
Mariano
3
Saya pikir Mariano menarik kaki kami tetapi tidak, itu benda <=>dan cukup akurat untuk boot!
HPWD
1
Perhatikan bahwa operator penggabungan nol berperilaku berbeda dari operator bersyarat, karena khusus untuk nullnilai. Misalnya, jika $_GET['name']diatur ke string kosong, baris pertama akan mengembalikan string kosong, tetapi kita bisa mengembalikan "john doe" dengan menggunakan $_GET['name'] ? $_GET['name'] : 'john doe'.
VPhantom
211

PHP 5.3 memiliki ?:operator singkatan :

$foo = $bar ?: $baz;

Yang menetapkan $barjika itu bukan nilai kosong (saya tidak tahu bagaimana ini akan berbeda dalam PHP dari Perl), jika tidak $baz, dan sama dengan ini di Perl dan versi PHP yang lebih lama:

$foo = $bar ? $bar : $baz;

Tapi PHP tidak memiliki operator penugasan majemuk untuk ini (yaitu, tidak ada yang setara dengan Perl ||=).

Selain itu, PHP akan mengeluarkan bunyi jika $bartidak disetel, kecuali jika Anda mematikan pemberitahuan. Ada juga perbedaan semantik antara isset()dan empty(). Yang pertama mengembalikan false jika variabel tidak ada, atau diatur ke NULL. Pengembalian yang terakhir benar jika itu tidak ada, atau diatur untuk 0, '', falseatau NULL.

BoltClock
sumber
2
+1 Untuk memperkenalkan saya ke fitur hebat lainnya dari 5.3, saya kehilangan server RHEL5 / PHP5.1.2 saya.
Michael Berkowski
Saya kira maksud Anda The first returnsalih-alih The seconddalam kalimat kedua dari belakang Anda.
Toto
21
Perhatikan bahwa jika variabel Anda tidak ditentukan, PHP akan memberikan pemberitahuan tentang hal itu. Sayangnya, ini bukan pengganti. $var = isset($var) ? $var : 'default value'; Dikatakan bahwa dalam jawabannya ... hanya menunjukkannya lagi kepada siapa pun yang melewatkannya. :-D
Brad
6
Apakah buruk melakukan $ var = @ $ var?: 'Nilai default'; Jika demikian, mengapa? Mengingat bahwa satu-satunya "kesalahan" adalah $ var tidak disetel, dan kami tidak peduli jika $ var tidak disetel ...
Codemonkey
8

Terima kasih atas semua jawaban hebatnya!

Bagi siapa pun yang datang ke sini untuk alternatif yang mungkin, berikut adalah beberapa fungsi yang membantu menghilangkan kejenuhan dari hal semacam ini.

function set_if_defined(&$var, $test){
    if (isset($test)){
        $var = $test;
        return true;
    } else {
        return false;
    }
}

function set_unless_defined(&$var, $default_var){
    if (! isset($var)){
        $var = $default_var;
        return true;
    } else {
        return false;
    }
}

function select_defined(){
    $l = func_num_args();
    $a = func_get_args();
    for ($i=0; $i<$l; $i++){
        if ($a[$i]) return $a[$i];
    }
}

Contoh:

// $foo ||= $bar;
set_unless_defined($foo, $bar);

//$foo = $baz || $bletch
$foo = select_defined($baz, $bletch);

Saya yakin ini bisa diperbaiki.

Tom Auger
sumber
7

Ungkapan umum untuk tetap kompatibel dengan versi PHP yang lebih lama adalah:

 $var = $bool   or   $var = "default";
 // If I use it, then only with excessive spaces for clarity.

Ini berfungsi untuk nilai-nilai yang dapat dievaluasi dalam konteks boolean. Keuntungannya di sini adalah ia juga memberi Anda kata debug e_notice jika variabelnya tidak ditentukan.

mario
sumber
Apakah pemberitahuan tidak dikeluarkan $bool ? $bool : "default"jika $booltidak ditetapkan?
BoltClock
Tentu, itu sama saja. Saya berasumsi OP mengacu isset($var) ? $var : DEFAULT. Tapi sepertinya dia ingin menghindari mereka.
mario
6

Dalam PHP lebih awal dari 7. *, orang dapat menggunakan?: Untuk variabel yang tidak ditentukan mengalami kesalahan secara lokal ditekan dengan @:

$foo = @$bar ?: $baz;
AndreyS Scherbakov
sumber
0

ini adalah format lain yang bagus untuk issetkasus ini

isset($foo) || $foo= $bar;

cara sederhana lain dan akan memberi Anda lebih banyak kontrol karena Anda dapat menambahkan lebih banyak kondisi dan menetapkan ke variabel lain secara bersamaan

$foo = (isset($oData['foo']))?$bar['foo']:'default value';

Bassem Shahin
sumber
0

Solusi yang mungkin: defaultFor ()

Kecuali jika kita memiliki solusi pabrik (yang memang sangat menjengkelkan), saya akan merekomendasikan pembantu kecil berikut. Itu melakukan pekerjaan dalam banyak kasus:


    function defaultFor(&$x,$default=null) {
        if(!isset($x)) $x = $default;
    }

    //--------------------  Now you can do this: --------------

    defaultFor($a,"Jack");  // if $a is not set, it will be "Jack"
    defaultFor($x);         // no more notices for $x but keep it !isset

Saya harap ini dekat dengan apa yang ingin Anda capai. Ini tidak akan memberi Anda pemberitahuan jika Anda menggunakannya dengan variabel yang tidak ada, dan itu cukup nyaman. Tentunya ia memiliki kekurangan: nilai default selalu dihitung sebelumnya, jadi jangan gunakan apa pun yang berat sebagai parameter kedua, seperti file_get_contents atau sesuatu. Dalam kasus itu, Anda lebih baik mengeluarkan.

dkellner
sumber