PHP的合并功能?
Posted
技术标签:
【中文标题】PHP的合并功能?【英文标题】:Coalesce function for PHP? 【发布时间】:2010-11-04 01:13:42 【问题描述】:许多编程语言都有一个合并函数(返回第一个非 NULL 值,example)。 php,遗憾的是在 2009 年没有。
在 PHP 本身获得合并函数之前,在 PHP 中实现一个的好方法是什么?
【问题讨论】:
相关:PHP 7 的新 null coalescing operator??
。
更多关于空合并操作符的信息可以在这里找到 - ***.com/questions/33666256/…
请注意,PHP7实现了这个功能
@Grzegorz: 运算符不是函数,或者你在哪里找到 PHP 7 中的新函数 ;)
功能我不是指功能;)功能。我说的不准确。谢谢你:)
【参考方案1】:
在谷歌上首次点击“php coalesce”。
function coalesce()
$args = func_get_args();
foreach ($args as $arg)
if (!empty($arg))
return $arg;
return NULL;
http://drupial.com/content/php-coalesce
【讨论】:
保存一点点内存,不要将 args 复制到数组中,只需执行 foreach(func_get_args() as $arg) @[Alfred,Ciaran] - 你错了。 foreach() 只对第一个参数求值一次,以获取一个数组,然后对其进行迭代。 将 func_get_args() 放入 foreach(此处为 $arg)从性能的角度来看不会改变任何东西。 @Savageman ...正是...如果您正在考虑从应用程序中挤出这一毫秒的性能或几个字节的内存,您可能正在寻找错误的性能/内存瓶颈跨度> 具有讽刺意味的是,这现在是 Google 上“php coalesce”的第一次点击。【参考方案2】:我目前正在使用它,但我想知道它是否无法通过 PHP 5 中的一些新功能进行改进。
function coalesce()
$args = func_get_args();
foreach ($args as $arg)
if (!empty($arg))
return $arg;
return $args[0];
【讨论】:
【参考方案3】:确保您准确地确定了您希望此函数如何与某些类型一起使用。 PHP 有各种各样的类型检查或类似功能,因此请确保您知道它们是如何工作的。这是 is_null() 和 empty() 的示例比较
$testData = array(
'FALSE' => FALSE
,'0' => 0
,'"0"' => "0"
,'NULL' => NULL
,'array()'=> array()
,'new stdClass()' => new stdClass()
,'$undef' => $undef
);
foreach ( $testData as $key => $var )
echo "$key " . (( empty( $var ) ) ? 'is' : 'is not') . " empty<br>";
echo "$key " . (( is_null( $var ) ) ? 'is' : 'is not') . " null<br>";
echo '<hr>';
如您所见,empty() 对所有这些都返回 true,但 is_null() 只对其中 2 个返回 true。
【讨论】:
【参考方案4】:php 5.3 中有一个新的操作符:?:
// A
echo 'A' ?: 'B';
// B
echo '' ?: 'B';
// B
echo false ?: 'B';
// B
echo null ?: 'B';
来源:http://www.php.net/ChangeLog-5.php#5.3.0
【讨论】:
多个三元快捷方式怎么样,例如“echo $a ?: $b ?: $c ?: $d;”工作吗? 对阵列无法按预期工作。例如,当尝试检查未定义的数组元素是否为假时,将导致错误。$input['properties']['range_low'] ?: '?'
无论使用 coalesce 运算符,您都应该收到未定义索引通知。
多个假参数返回最后一个参数,array() ?: null ?: false
返回false
。运营商确实很理智。
请记住,这不仅接受非空值,如其他语言中的合并,还接受任何值,这些值将被隐式转换为布尔值。因此,请确保您更新您的type casting rules【参考方案5】:
值得注意的是,由于 PHP 对未初始化变量和数组索引的处理,任何类型的合并函数的使用都是有限的。我希望能够做到这一点:
$id = coalesce($_GET['id'], $_SESSION['id'], null);
但是,在大多数情况下,这会导致 PHP 出现 E_NOTICE 错误。在使用变量之前测试变量是否存在的唯一安全方法是直接在 empty() 或 isset() 中使用它。如果您知道合并中的所有选项都已知已初始化,则 Kevin 建议的三元运算符是最佳选择。
【讨论】:
在这种情况下,数组联合工作得很好 ($getstuff = $_GET+$_SESSION+array('id'=>null);$id=$getstuff['id'];
)。
@Quill 那应该是什么意思?您是否参考了建议的解决方案?
PHP 7 引入了可爱的新isset ternary 运算符??
使这个非常常见的操作更加简洁。【参考方案6】:
我真的很喜欢 ?: 运算符。不幸的是,它还没有在我的生产环境中实现。所以我使用这个等价物:
function coalesce()
return array_shift(array_filter(func_get_args()));
【讨论】:
这是一个“真实”的合并,使用 array_filter 去除传入的 n 个参数中任何评估为假(包括 null)的内容。我的猜测是使用 shift 而不是第一个元素数组在某种程度上更健壮,但那部分我不知道。见:php.net/manual/en/… 我喜欢它,但必须同意@hakre -coalesce
应该返回它遇到的第一个 non-null 参数,其中包括 FALSE
。不过,这个函数会丢弃 FALSE
,可能不是 op 想要的(至少不是我想要的 coalesce
函数)。
只有变量应该通过引用传递【参考方案7】:
我正在扩展Ethan Kent 发布的答案。由于array_filter 的内部工作原理,该答案将丢弃评估为假的非空参数,而coalesce
函数通常不会这样做。例如:
echo 42 === coalesce(null, 0, 42) ? 'Oops' : 'Hooray';
哎呀
为了克服这个问题,需要第二个参数和函数定义。 callable 函数负责告诉array_filter
是否将当前数组值添加到结果数组中:
// "callable"
function not_null($i)
return !is_null($i); // strictly non-null, 'isset' possibly not as much
function coalesce()
// pass callable to array_filter
return array_shift(array_filter(func_get_args(), 'not_null'));
如果您可以简单地将isset
或'isset'
作为第二个参数传递给array_filter
,那就太好了,但没有这样的运气。
【讨论】:
【参考方案8】:PHP 5.3+,带闭包:
function coalesce()
return array_shift(array_filter(func_get_args(), function ($value)
return !is_null($value);
));
演示:https://eval.in/187365
【讨论】:
只有变量应该通过引用传递 是的,为了简单起见,我打破了演示的严格规则。 :)【参考方案9】:PHP 7 引入了真正的coalesce operator:
echo $_GET['doesNotExist'] ?? 'fallback'; // prints 'fallback'
如果??
之前的值不存在或者是null
,则取??
之后的值。
对上述?:
运算符的改进在于,??
还可以处理未定义的变量,而不会抛出E_NOTICE
。
【讨论】:
终于不再到处都是isset()和empty()了! @timeNomad 你仍然需要是空的,它只检查 null 获得安全“falsy-coalesce”的唯一方法是同时使用两者:($_GET['doesNotExist'] ?? null) ?: 'fallback'
然而,?:
相对于??
的优势在于它还合并了空值,而??
没有这样做。类似于 javascript 中逻辑 OR 运算符的行为(即$val || 'default'
),如果在我们的实践中我们最终发现自己同时处理 empty 和 null 以相同的方式(即$val ?: 'default'
)。如果你想进一步强迫这个问题并吞下E_NOTICE
,你甚至可以争论:echo @$val ?: 'default';
以上是关于PHP的合并功能?的主要内容,如果未能解决你的问题,请参考以下文章