【问题标题】:More concise ternary expression?更简洁的三元表达式?
【发布时间】:2012-07-20 07:02:01
【问题描述】:

我经常发现自己需要使用以下逻辑模式编写代码:

$foo = isset($bar) ? $bar : $baz;

我知道?: 语法:

$foo = $bar ?: $baz;

...从表面上看,这似乎是我正在寻找的东西;但是,当未设置 $bar 时,它会引发未定义的通知索引。它还使用与empty() 相同的逻辑,这意味着像FALSE0"0" 等“空”值不会通过。因此,它并不真正等同。

$bar 未设置时,是否有更短的方法来编写代码而不发出通知?

编辑:

为了更清楚一点为什么我正在寻找一种快捷语法,这里有一个更好的例子:

$name = isset($employee->getName())
      ? $employee->getName()
      : '<unknown>';

在这种情况下,$employee 可能是来自第 3 方库的对象,它的 name 可能是 NULL 可能是一个有效的场景。我想将变量 $name 设置为返回的名称(如果有的话),但如果没有的话,一些合理的默认值。

如果方法调用比 getter 更复杂,那么示例会变得更加冗长,因为我们必须缓存结果:

$bar = $some->reallyExpensiveOperation();
$foo = isset($bar) ? $bar : $baz;

【问题讨论】:

  • 想一想:在一个表达式中,您想检查是否存在避免通知(isset() 这样做),如果已设置,则设置为第一个变量,否则设置为第二个?你有两个选择:第一个是你提出的,第二个是让通知静音。
  • 你可以禁止警告:$foo = @$bar ?: $baz;... 但我不会那样做。
  • 你的生活一定很忙,无法在这几秒钟内输入isset等。
  • 在编写此类代码时可能会节省一些字符,但在调试时,它很快就会变成浪费时间的噩梦。我完全不鼓励任何使用这种神秘代码的人。但这是你的代码,做任何你想做的事......
  • @EdHeal:这个论点永远不会赢。大多数现代编程语言中实现的大量内容是语法糖和快捷方式。哎呀,三元运算符本身就是这样。

标签: php ternary-operator


【解决方案1】:

如果没有定义$bar,就没有真正“更短”的方式来编写相同的代码。

有两个,我认为“黑客”可以做到这一点,但是,它们也可能会影响其他事情:

  1. 使用@ 限制错误,例如$foo = @$bar ?: $baz; 将 完全按照您的意愿行事并限制未定义的错误 当$bar 未定义时抛出。如果它被定义,它也将起作用 如预期的。然而,缺点是@ 会降低效率 如果重复使用,请在您的代码中。
  2. 关闭通知 error_reporting(E_ALL &amp; ~E_NOTICE);。这仍将显示所有 常规错误,但不是通知,这将有效地隐藏 “变量未定义”错误。这样做的缺点是你 不会看到任何其他通知。

现在,我的强制性个人意见,我建议继续完整地写出来。三元运算符已经是简写,有效地减少了以下内容:

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

变得更短

$foo = isset($bar) ? $bar : $baz;

编写完整的三元组和较短的三元组真的不需要太多的努力(当然,除非你的变量名长得离谱)。此外,在很多情况下,复合三元运算(即,多个三元合二为一)会导致超速记无法使用;所以短期储蓄在程序上/道德上并不令人满意(在我看来)。

更新:为了支持您将 $bar 分配给函数的返回值然后基于它的 $foo 的编辑 - 您可以将语句组合成一个- 行如:

$foo = (($bar = $some->reallyExpensiveOperation()) != null) ? $bar : $baz;

这与这两行的代码长度几乎相同,但也可以从这里稍微缩短。例如,如果 null 不是您认为“无效”的唯一值,但 false 也很重要,您可以完全删除 != null 部分并允许将条件视为简单的布尔值:

$foo = ($bar = $some->reallExpensiveOperation()) ? $bar : $baz;

在这个例子中,$bar 在三元运算之后仍然可以访问(即,它不会失去作用域),所以除非你需要对变量进行预处理,否则这种方法没有太大的缺点,除了可读性。

【讨论】:

    【解决方案2】:

    当您显式预定义变量或使用带有魔法吸气剂的对象时,我只会使用简写三元语法。这是我通常使用速记三元语法的一个非常基本的示例

    class Foo {
        public function __get($name) {
            return isset($this->{$name}) ? $this->{$name} : '';
        }
    }
    
    $foo = new Foo();
    $bar = $foo->baz ?: 'default';
    

    【讨论】:

      【解决方案3】:

      使用error control operator,您可以在技术上将其缩短为:

      $foo = @$bar ?: $baz;
      

      如果未设置 $bar,则该值的计算结果为 null,并且您不会收到错误通知,因为您已抑制错误。然而,有些人可能不赞成这段代码,因为它不适合使用 @,因为它掩盖了错误并使调试更加困难。

      没有它,不,我不相信有一个更短的符号只使用isset

      编辑:正如@drrcknlsn 所指出的,如果变量是false,或0,甚至null,这将不起作用,所以在我看来,没有避免调用@ 987654329@.

      【讨论】:

      • Pssh -1,问题的有效答案。 OP 要求更短的表达式,并且更短。
      • 我没有投反对票,但我也不能投赞成票,因为我真的不想在生产代码中看到这样的东西。
      • 我 +1 以抵消它。有些人不理解 SO 评级。 :-P
      • 我不会按照你的建议去做,我反对你的回答,但我不会因为这个原因而投反对票:这只是这个问题的有效答案。
      • @nickb 我看到你的评论弹出了相同的答案,就在我完成输入答案的时候。我同意,我不会使用它,但把它和问题的技术答案一起扔了出去。
      猜你喜欢
      • 2012-11-15
      • 2013-10-15
      • 1970-01-01
      • 2011-06-17
      • 2013-02-25
      • 1970-01-01
      • 2011-03-27
      • 2013-08-29
      • 1970-01-01
      相关资源
      最近更新 更多