更简洁的三元表达?

时间:2012-07-21 01:59:16

标签: php ternary-operator

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

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

我知道?:语法:

$foo = $bar ?: $baz;

......从表面上看,它似乎正是我所寻找的;但是,如果未设置$bar,它会抛出一个未定义的通知索引。它也使用与empty()相同的逻辑,这意味着FALSE0"0"等“空”值不会通过。因此,它并不是真正的等价物。

如果没有设置$bar,是否有更短的方式编写代码而不会发出通知?

修改

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

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

在这种情况下,$employee可能是第三方库中的对象,而name可能是NULL的有效方案可能是{1}}。我想将变量$name设置为返回的名称(如果有的话),但如果没有,则设置一些合理的默认值。

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

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

3 个答案:

答案 0 :(得分:3)

当您明确预定义变量或使用带魔法吸气剂的对象时,我只会使用简写三元语法。这是我通常使用短手三元语法

的一个非常基本的例子
class Foo {
    public function __get($name) {
        return isset($this->{$name}) ? $this->{$name} : '';
    }
}

$foo = new Foo();
$bar = $foo->baz ?: 'default';

答案 1 :(得分:0)

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

$foo = @$bar ?: $baz;

如果未设置$bar,则值的计算结果为null,并且由于您抑制了错误,因此没有错误通知。但是,有些人可能不赞同使用此代码,因为它使用@并不好用,因为它会掩盖错误并使调试更加困难。

如果没有这个,我不相信只使用isset会有一个较短的符号。

编辑:正如@drrcknlsn所说,如果变量是false0,甚至是null,这将不起作用,所以在我看来,没有避免调用isset

答案 2 :(得分:0)

如果未定义$bar,则不会更短&#34;更短的&#34;编写相同代码的方法。

有两个,我会考虑什么&#34; hacks&#34;然而,要做到这一点,它们也可能影响其他事情:

  1. 使用@进行错误限制,例如$foo = @$bar ?: $baz;会 完全按照自己的意愿行事并限制未定义的错误 $bar未定义时抛出。如果已定义,它也将起作用 如预期的。然而,缺点是@会降低效率 在你的代码中,如果反复使用它。
  2. 关闭通知 error_reporting(E_ALL & ~E_NOTICE);。这仍将显示全部 常规错误,但不是通知,这将有效隐藏 &#34;变量未定义&#34;错误。这样做的缺点是你 不会看到任何其他通知。
  3. 现在,我的强制性个人意见,我建议继续全力以赴。三元运算符已经是速记,有效地减少了以下内容:

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

    进入更短的

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

    并且它真的不需要花费更多的精力来编写完整的三元与较短的三元(当然,除非你的变量名称非常长)。此外,复合三元操作(即 - 一个中的几个三元组)将导致超速简化无法使用;因此,短期储蓄在编程上/道德上并不令人满意(在我看来)。

    更新:为了支持您的编辑,您可以将$bar分配给某个功能的返回值,然后$foo根据它进行分配 - 您可以将语句组合成单行,如:

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

    这与两条线的代码长度几乎相同,但也可以从这里略微缩短。例如,如果null不是您考虑的唯一值&#34;无效&#34;,但false也会计算,则可以完全删除!= null部分并允许将条件视为一个简单的布尔值:

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

    在这个例子中,$bar在三元操作之后仍然可以访问(即 - 它不会失去范围),所以除非你需要对变量进行预处理,否则不会出现这种情况。除了可读性之外,这种方法的重大缺点。