赋予变量默认值的最佳方法(模拟Perl ||,|| =)


134

我喜欢在Perl中做这种事情:$foo = $bar || $baz分配$baz$foo是否$bar为空或未定义。您还可以$foo ||= $bletch将只分配$bletch$foo如果$foo没有定义或清空。

在这种情况下,三元运算符既繁琐又累人。当然,PHP中提供了一种简单,优雅的方法吗?

还是唯一的答案是使用isset()的自定义函数?



1
顺便说一句,具有所需功能的Perl运算符为//and //=,它们从Perl v5.10.0开始存在。原始||||=测试逻辑值,而不是定义性。
Palec

@Palec,为什么将一个具有29个投票的4年老问题识别为一个具有6个投票的1年老问题的重复(它本身被标记为另一个问题的重复?)我认为保留此点很有价值问题,因为标题更通用(不引用答案,即:isset())。
汤姆·奥格

它们是清晰准确的重复项。它承认我对哪个应该是原件没有太多的考虑,我处于其他方面,将两者之间的联系作为目标。收回我的VTC。
Palec 2015年

完全相同的副本,被标记为(IMO错误)为另一个问题的副本:isset()的PHP速记?
Palec 2015年

Answers:


130

在PHP 7中,我们终于有了一种优雅的方法。它称为Null合并运算符。您可以像这样使用它:

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

这相当于

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

14
我认为太空飞船运营商也有好处。
马里亚诺

3
我以为Mariano会拉我们的腿,但不会,这是一件<=>非常准确的事情!
HPWD

1
请注意,空值合并运算符的行为与条件运算符不同,因为它特定于null值。例如,如果$_GET['name']设置为空字符串,第一行将返回一个空字符串,但是我们可以使用来返回“ john doe” $_GET['name'] ? $_GET['name'] : 'john doe'
幻影

211

PHP 5.3有一个简写的?:运算符:

$foo = $bar ?: $baz;

$bar如果它不是一个空值,则分配该值(我不知道这在PHP中与Perl有什么不同),否则$baz,与Perl和旧版本的PHP中的相同:

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

但是PHP没有为此使用复合赋值运算符(也就是说,没有Perl的等效运算符||=)。

此外,如果$bar未设置,除非关闭通知,否则PHP会发出噪音。isset()和之间还有语义上的区别empty()。如果变量不存在或设置为,则前者返回false NULL。后者返回true,如果它不存在,或者设置为0''falseNULL


2
+1为了向我介绍5​​.3的另一个强大功能,我在RHEL5 / PHP5.1.2服务器中错过了一些功能。
Michael Berkowski

我想你的意思The first returns不是The second倒数第二句话。
多托

21
请注意,如果您的变量未定义,PHP将引发有关该变量的通知。不幸的是,$var = isset($var) ? $var : 'default value'; 这并不能替代它。它说,在答案中……只是将其指出给所有略过它的人。:-D
Brad

6
$ var = @ $ var是否不好?:'default value'; 如果是这样,为什么?鉴于唯一的“错误”可能是未设置$ 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.

这适用于可以在布尔上下文中评估的值。这样做的好处是,如果变量未定义,它还会给您说debug e_notice。


$bool ? $bool : "default"如果$bool未定义,是否不发出通知?
BoltClock

当然可以。我以为OP是指isset($var) ? $var : DEFAULT。但是听起来他还是想避开他们。
马里奥


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

我希望这接近您想要实现的目标。如果将它与不存在的变量一起使用,它不会给您任何提示,这非常方便。当然,它有一个缺点:默认值总是预先计算出来的,因此不要将它与重的第二个参数一起使用,例如file_get_contents之类的东西。在这种情况下,最好使用固定设置。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.