PHP 的合并函数?
-
06-07-2019 - |
题
许多编程语言都有合并函数(返回第一个非 NULL 值, 例子)。遗憾的是,2009 年 PHP 还没有做到这一点。
在 PHP 本身获得合并函数之前,在 PHP 中实现一个合并函数的好方法是什么?
解决方案
php 5.3中有一个新的运算符,它执行此操作:?:
// A
echo 'A' ?: 'B';
// B
echo '' ?: 'B';
// B
echo false ?: 'B';
// B
echo null ?: 'B';
其他提示
首次点击“php coalesce”在谷歌。
function coalesce() {
$args = func_get_args();
foreach ($args as $arg) {
if (!empty($arg)) {
return $arg;
}
}
return NULL;
}
我真的很喜欢?:运算符。不幸的是,它还没有在我的生产环境中实现。所以我使用相当于:
function coalesce() {
return array_shift(array_filter(func_get_args()));
}
值得注意的是,由于 PHP 对未初始化变量和数组索引的处理,任何类型的合并函数的用途都是有限的。我很想能够做到这一点:
$id = coalesce($_GET['id'], $_SESSION['id'], null);
但在大多数情况下,这会导致 PHP 出错并显示 E_NOTICE。在使用变量之前测试变量是否存在的唯一安全方法是直接在empty() 或isset() 中使用它。如果您知道合并中的所有选项都已初始化,则 Kevin 建议的三元运算符是最佳选择。
确保您确切地确定此功能如何与某些类型一起使用。 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。
我正在扩展 Ethan Kent 发布的答案。由于的内部工作原因,该答案将丢弃评估为false的非空参数。 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
的第二个参数传递,那就太好了,但没有这样的运气。
我目前正在使用它,但我想知道是否使用PHP 5中的一些新功能无法改进它。
function coalesce() {
$args = func_get_args();
foreach ($args as $arg) {
if (!empty($arg)) {
return $arg;
}
}
return $args[0];
}
PHP 5.3+,带闭包:
function coalesce()
{
return array_shift(array_filter(func_get_args(), function ($value) {
return !is_null($value);
}));
}