给变量一个默认值的最好方法(模拟 Perl ||, ||= )
Posted
技术标签:
【中文标题】给变量一个默认值的最好方法(模拟 Perl ||, ||= )【英文标题】:Best way to give a variable a default value (simulate Perl ||, ||= ) 【发布时间】:2011-08-23 18:30:39 【问题描述】:我喜欢在 Perl 中做这样的事情:如果 $bar
为空或未定义,$foo = $bar || $baz
将 $baz
分配给 $foo
。您还有$foo ||= $bletch
,它只会在$foo
未定义或为空时将$bletch
分配给$foo
。
这种情况下的三元运算符既乏味又令人厌烦。 php 中肯定有一个简单、优雅的方法吗?
或者唯一的答案是使用 isset() 的自定义函数?
【问题讨论】:
相关Code Review:codereview.stackexchange.com/q/12722/31433 顺便说一句,具有所需功能的 Perl 运算符是//
和 //=
,它们从 Perl v5.10.0 开始存在。原始的 ||
和 ||=
测试逻辑值,而不是定义性。
@Palec,为什么一个 4 年有 29 个赞的问题会被识别为一个 1 年有 6 个赞的问题的副本(它本身被标记为另一个问题的副本?)我认为保留这个问题很有价值,因为标题更通用(没有引用答案,即:isset())。
它们是清晰准确的重复。它承认我没有想太多应该是原始的,我正处于其他事情的中间,在两者之间建立联系是目标。收回我的 VTC。
完全重复,标记(IMO 错误)为另一个问题的重复:PHP shorthand for isset()?
【参考方案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
、''
、false
或NULL
时返回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),只有 false
和 nil
是错误的,这意味着 0
和 1
都是正确的。由于这种跨语言的歧义,我认为在这些情况下最好是明确的:
if ($bar !== 0)
$foo = $bar;
else
$foo = $baz;
或:
$foo = $bar !== 0 ? $bar : $baz;
【讨论】:
以上是关于给变量一个默认值的最好方法(模拟 Perl ||, ||= )的主要内容,如果未能解决你的问题,请参考以下文章