Найкращий спосіб надати змінній значення за замовчуванням (імітувати Perl ||, || =)


134

Я люблю робити такі речі в Perl: $foo = $bar || $bazпризначити $bazв $fooразі $barпорожній або не визначене. У вас також є , $foo ||= $bletchякі будуть призначати тільки $bletchв $fooразі $fooне визначений або порожній.

Потрійний оператор у цій ситуації стомлюючий і стомливий. Напевно, в PHP є простий, елегантний метод?

Або єдиною відповіддю є власна функція, яка використовує isset ()?



1
До речі оператори Perl з необхідною функціональністю //і , //=і вони існують як в Perl v5.10.0. Оригінал ||і ||=тест на логічне значення, а не на визначеність.
Palec

@Palec, чому б 4-річне запитання з 29 оновленими ідентифікаторами було визначено як дублікат 1-річного запитання з 6 оновленими запитаннями (що саме позначено як дублікат іншого питання?) Я думаю, що це має велике значення для цього питання, як заголовок більш загальний (не посилається на відповідь, тобто: isset ()).
Том Ожер

Вони чіткі і точні дублікати. Зізнаюсь, я не надто замислювався над тим, який з них повинен бути оригіналом, я опинився в середині чогось іншого, мета мети між цими двома була метою. Відкликання мого VTC.
Палець

Точний дублікат, позначений (помилково IMO) як дублікат іншого питання: PHP-стенограма для isset ()?
Палець

Відповіді:


130

У PHP 7, нарешті, є спосіб зробити це елегантно. Його називають оператором злиття Null . Ви можете використовувати його так:

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

Це еквівалентно

$name = isset($_GET['name']) ? $_GET['name']:'john doe';

14
Я б стверджував, що заслуговує і оператор космічного корабля .
Маріано

3
Я подумав, що Маріано тягне наші ноги, але ні, це - річ <=>і досить акуратна для завантаження!
HPWD

1
Зауважимо, що оператор, що поєднує нуль, поводиться інакше, ніж умовний оператор, оскільки він специфічний для nullзначення. Наприклад, якщо $_GET['name']встановлено порожній рядок, перший рядок поверне порожню рядок, але ми можемо повернути "john doe" за допомогою $_GET['name'] ? $_GET['name'] : 'john doe'.
VPhantom

211

PHP 5.3 має ?:оператор скорочення :

$foo = $bar ?: $baz;

Що призначає, $barякщо це не порожнє значення (я не знаю, чим це буде відрізнятися в PHP від ​​Perl), інакше $baz, і це те саме, що це в Perl та старих версіях PHP:

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

Але PHP не має для цього оператора присвоєння складених даних (тобто немає еквівалента Perl ||=).

Крім того, PHP видасть шум, якщо $barйого не встановлено, якщо ви не відключите повідомлення. Існує також смислова різниця між isset()і empty(). Перший повертає значення false, якщо змінна не існує або встановлена ​​на NULL. Останні повертає істину , якщо вона не існує, або має значення 0, '', falseабо NULL.


2
+1 Для того, щоб познайомити мене з ще однією чудовою особливістю 5,3, яку я не вистачає на своїх серверах RHEL5 / PHP5.1.2.
Майкл Берковський

Я думаю, ви маєте на увазі The first returnsзамість The secondсвого передостаннього речення.
Toto

21
Зауважте, що якщо ваша змінна не визначена, PHP буде кидати повідомлення про неї. Це, на жаль, не є заміною. $var = isset($var) ? $var : 'default value'; Це говорить про те, що у відповіді ... просто вказуючи це знову для тих, хто його скидає. :-D
Бред

6
Чи погано робити $ var = @ $ var?: 'Значення за замовчуванням'; Якщо так, то чому? Враховуючи, що єдиною "помилкою" може бути те, що $ var не встановлено, і що нас не хвилює, якщо $ var не встановлено ...
Codemonkey

8

Дякую за всі чудові відповіді!

Для всіх, хто приходить сюди за можливою альтернативою, ось кілька функцій, які допомагають зняти нудьгу з подібних речей.

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];
    }
}

Приклади:

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

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

Я впевнений, що це можна покращити.


7

Загальна ідіома, яка залишається сумісною з більш старими версіями PHP:

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

Це працює для значень, які можна оцінити в булевому контексті. Перевага тут полягає в тому, що він також дає вам вказати налагодження e_notice у випадку, якщо змінна не буде визначена.


Чи не надсилається повідомлення, $bool ? $bool : "default"якщо $boolйого не визначено?
BoltClock

Звичайно, це те саме. Я припускав, що ОП має на увазі isset($var) ? $var : DEFAULT. Але звучить так, ніби він хоче їх уникнути.
Маріо

6

У PHP раніше, ніж 7. *, можна використовувати?: Для невизначеної змінної, що локально придушується помилками з @:

$foo = @$bar ?: $baz;

0

це ще один хороший формат для issetсправи

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

інший простий спосіб і надасть вам більше контролю, оскільки ви можете додати більше умов і призначити іншу змінну за той же час

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


0

Можливе рішення: defaultFor ()

Якщо у нас немає фабричного рішення (що насправді дуже дратує), я рекомендую наступного маленького помічника. Це робить роботу в більшості випадків:


    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

Я сподіваюся, що це близько до того, що ви хотіли досягти. Він не дасть вам жодних повідомлень, якщо ви використовуєте його з неіснуючою змінною, і це досить зручно. Звичайно, у нього є недолік: значення за замовчуванням завжди обчислюється заздалегідь, тому не використовуйте його з чимось важким як другий параметр, наприклад, файл_get_contents або щось подібне. У цих випадках вам краще пограбувати.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.