【问题标题】:Best way to give a variable a default value (simulate Perl ||, ||= )给变量一个默认值的最好方法(模拟 Perl ||, ||= )
【发布时间】:2011-08-23 18:30:39
【问题描述】:

我喜欢在 Perl 中做这样的事情:如果 $bar 为空或未定义,$foo = $bar || $baz$baz 分配给 $foo。您还有$foo ||= $bletch,它只会在$foo 未定义或为空时将$bletch 分配给$foo

这种情况下的三元运算符既乏味又令人厌烦。 PHP 中肯定有一个简单、优雅的方法吗?

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

【问题讨论】:

  • 顺便说一句,具有所需功能的 Perl 运算符是 ////=,它们从 Perl v5.10.0 开始存在。原始的 ||||= 测试逻辑值,而不是定义性。
  • @Palec,为什么一个 4 年有 29 个赞的问题会被识别为一个 1 年有 6 个赞的问题的副本(它本身被标记为另一个问题的副本?)我认为保留这个问题很有价值,因为标题更通用(没有引用答案,即:isset())。
  • 它们是清晰准确的重复。它承认我没有想太多应该是原始的,我正处于其他事情的中间,在两者之间建立联系是目标。收回我的 VTC。
  • 完全重复,标记(IMO 错误)为另一个问题的重复:PHP shorthand for isset()?

标签: php perl operators default-value


【解决方案1】:

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

$foo = $bar ?: $baz;

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

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

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

另外,如果没有设置$bar,PHP 会发出噪音,除非你关闭通知。 isset()empty() 之间也存在语义差异。如果变量不存在或设置为NULL,则前者返回false。后者在不存在或设置为0''falseNULL 时返回true。

【讨论】:

  • +1 为了向我介绍 5.3 的另一个重要功能,我错过了我的 RHEL5/PHP5.1.2 服务器。
  • 我猜你的意思是The first returns,而不是倒数第二句中的The second
  • 请注意,如果您的变量未定义,PHP 将发出有关它的通知。不幸的是,这不能替代$var = isset($var) ? $var : 'default value'; 它在答案中说......只是为任何浏览它的人再次指出它。 :-D
  • 做 $var = @$var 是不是很糟糕?:'默认值';如果是这样,为什么?鉴于唯一的“错误”可能是 $var 未设置,并且我们不在乎 $var 是否未设置...
【解决方案2】:

在 PHP 7 中,我们终于有办法优雅地做到这一点。它被称为Null coalescing operator。你可以这样使用它:

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

这相当于

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

【讨论】:

  • 我认为spaceship operator 也有优点。
  • 我以为马里亚诺在拉扯我们的腿,但不是的,这是 <=> 并且非常准确!
  • 请注意,空合并运算符的行为与条件运算符不同,因为它特定于 null 值。例如,如果$_GET['name'] 设置为空字符串,第一行将返回一个空字符串,但我们可以使用$_GET['name'] ? $_GET['name'] : 'john doe' 返回“john doe”。
  • @Mariano 是的,但宇宙飞船操作员与这里有什么关系?
【解决方案3】:

感谢所有精彩的答案!

对于其他来这里寻找可能替代方案的人,这里有一些功能可以帮助您摆脱这种乏味的事情。

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

我相信这些可以改进。

【讨论】:

    【解决方案4】:

    与旧 PHP 版本保持兼容的常见习惯用法是:

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

    这适用于可以在布尔上下文中评估的值。这里的好处是,如果变量未定义,它还可以为您提供调试 e_notice。

    【讨论】:

    • 如果$bool 未定义,通知是否与$bool ? $bool : "default" 一起发出?
    • 当然,也一样。我假设 OP 指的是isset($var) ? $var : DEFAULT。但听起来他无论如何都想避开他们。
    【解决方案5】:

    在早于 7.* 的 PHP 中,可以将 ?: 用于未定义的变量,该变量在本地使用 @ 抑制错误:

    $foo = @$bar ?: $baz;
    

    【讨论】:

      【解决方案6】:

      这是isset 案例的另一种好格式

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

      另一种简单的方法,可以让您获得更多控制权,因为您可以添加更多条件并同时分配给另一个变量

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

      【讨论】:

        【解决方案7】:

        一个可能的解决方案: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 或其他东西。在这些情况下,最好使用 isseting。

        【讨论】:

          【解决方案8】:

          我认为通常会做这样的事情:

          $foo = $bar || $baz;
          

          是个坏主意,除非 $bar$baz 都是布尔值。如果不是:

          $bar = 10;
          $baz = 11;
          

          那么问题就变成了:是什么决定了事物的真假?大多数人可能会认为零是假的,而其他一切都是真的。但是对于某些语言(例如 Ruby),只有 falsenil 是错误的,这意味着 01 都是正确的。由于这种跨语言的歧义,我认为在这些情况下最好是明确的:

          if ($bar !== 0) {
             $foo = $bar;
          } else {
             $foo = $baz;
          }
          

          或:

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

          【讨论】:

            猜你喜欢
            • 2011-04-15
            • 1970-01-01
            • 1970-01-01
            • 2021-09-19
            • 2011-04-30
            • 2012-10-23
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多