6

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

$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;
4

3 回答 3

3

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

class Foo {
    public function __get($name) {
        return isset($this->{$name}) ? $this->{$name} : '';
    }
}

$foo = new Foo();
$bar = $foo->baz ?: 'default';
于 2012-07-21T02:14:30.933 回答
0

使用错误控制运算符,您可以在技术上将其缩短为:

$foo = @$bar ?: $baz;

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

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

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

于 2012-07-21T02:03:55.177 回答
0

$bar未定义时,实际上没有“更短”的方式来编写相同的代码。

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

  1. 使用 进行错误限制@,例如$foo = @$bar ?: $baz;将完全按照您的意愿执行并限制未定义时抛出的未定义错误$bar。如果它被定义,它也将按需要工作。但是,不利的一面是,@如果重复使用它会降低代码的效率。
  2. 用 关闭通知 error_reporting(E_ALL & ~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在三元运算之后仍然可以访问(即 - 它不会失去作用域),所以除非你需要对变量进行预处理,否则除了可读性之外,这种方法没有很大的缺点。

于 2012-07-21T03:15:47.447 回答