PHP的合并功能?


131

许多编程语言都有合并函数(返回第一个非NULL值,例如)。可悲的是,PHP在2009年没有。

在PHP本身获得合并功能之前,用PHP实现一个的好方法是什么?


11
相关阅读:新的空合并运算符 ??的PHP 7
小次郎

有关空合并运算符的更多信息,请参见此处-stackoverflow.com/questions/33666256/…–
Peter

1
只需注意,PHP7实现了此功能
Grzegorz

@Grzegorz:运算符不是函数,或者您在哪里找到了PHP 7中新的函数;)
hakre

按功能我不是指功能;)功能。我不精确。谢谢您:)
Grzegorz

Answers:


194

在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


25
那么多个三元快捷方式呢?例如“ echo $ a?:$ b?:$ c?:$ d;”。工作?
克里斯(ChrisR)2010年

5
对于阵列无法正常工作。例如,当尝试检查未定义的数组元素是否为false时,将导致错误。 $input['properties']['range_low'] ?: '?'
Keyo

5
无论使用合并运算符如何,您都应该获得“未定义索引”通知。
凯文

2
多falsey参数返回的最后一个参数,array() ?: null ?: false返回false。操作员确实很理智。
布莱德·科赫

6
请记住,这不仅像其他语言中的合并一样接受非null,还接受任何值,这些值将隐式转换为布尔值。因此,请确保您遵守类型转换规则
DanMan 2014年

65

PHP 7引入了一个真正的合并运算符

echo $_GET['doesNotExist'] ?? 'fallback'; // prints 'fallback'

如果之前的值??不存在或者是null之后的值??

对上述?:运算符的改进是,,该运算符??还可以处理未定义的变量而不会引发E_NOTICE


最后,到处都不再有isset()和empty()了!
乔治·卡根

7
@timeNomad您仍然需要将其为空,它仅检查空值
Nabeel Khan

获得安全的“虚假假冒”的唯一方法是同时使用以下两者:($_GET['doesNotExist'] ?? null) ?: 'fallback'
内森·鲍尔奇

但是,?:over 的优点??在于,它也可以合并空值,而??不会合并。与JavaScript中逻辑OR运算符的行为类似(即$val || 'default'),如果在我们的实践中最终发现自己以相同的方式处理空值空值(即),我会发现?:这是一种更实用的合并形式。而且,如果您想进一步加剧和吞并这个问题,甚至可以提出以下质疑:$val ?: 'default'E_NOTICEecho @$val ?: 'default';
马特·博尔贾

29

首次在Google上投放“ 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


9
保存
一小段

17
@ [Alfred,Ciaran]-您不正确。foreach()仅对第一个参数求值一次,以获得一个数组,然后对其进行迭代。
gahooa

6
从性能的角度来看,将func_get_args()放入foreach(在这里为$ arg)不会改变任何内容。
Savageman

7
@Savageman ...恰好...如果您正在考虑从应用程序中压缩毫秒级的性能或几字节的内存,则可能是错误的性能/内存瓶颈
ChrisR 2010年

4
具有讽刺意味的是,这现在是Google上“ php合并”的首个热门产品。
Will Shaver 2014年

18

我真的很喜欢?:运算符。不幸的是,它尚未在我的生产环境中实现。所以我使用了等效的方法:

function coalesce() {
  return array_shift(array_filter(func_get_args()));
}

1
这是一个“真实的”结合,使用array_filter来消除传入的n个参数中任何结果为false(包括null)的东西。我的猜测是使用shift而不是数组中的第一个元素更可靠,但是部分我不知道。见:php.net/manual/en/...
亚当托利

3
我喜欢它,但必须同意@hakre- coalesce应该返回遇到的第一个非null参数,其中包括FALSEFALSE但是,此函数将丢弃,可能不是op所考虑的(至少不是我想要从coalesce函数中获取的)。
Madbreaks

1
只有变量应该通过引用传递
Ben Sinclair 2015年

9

值得注意的是,由于PHP对未初始化的变量和数组索引的处理,所以任何种类的合并函数的用途都是有限的。我希望能够做到这一点:

$id = coalesce($_GET['id'], $_SESSION['id'], null);

但是,在大多数情况下,这将导致PHP出现E_NOTICE错误。在使用变量之前测试变量是否存在的唯一安全方法是直接在empty()或isset()中使用它。如果您知道合并中的所有选项都已初始化,则Kevin建议的三元运算符是最佳选择。


在这种情况下,数组并集可以很好地工作($getstuff = $_GET+$_SESSION+array('id'=>null);$id=$getstuff['id'];)。
Brilliand 2014年

@Quill这是什么意思?您是否提出了建议的参考解决方案?
本辛克莱

PHP 7引入了可爱的新isset三元运算符,??以使此非常常见的操作更加简洁。
botimer

6

确保准确确定希望此功能与某些类型一起使用的方式。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。


2

我在扩展Ethan Kent发布的答案。由于array_filter的内部工作原理,该答案将舍弃评估为false的非null参数,而这通常不是coalesce函数通常要做的。例如:

echo 42 === coalesce(null, 0, 42) ? 'Oops' : 'Hooray';

哎呀

为了克服这个问题,需要第二个参数和函数定义。的可调用的功能是负责告诉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,但没有这种运气,那将是很好的。


0

我目前正在使用它,但是我想知道是否无法使用PHP 5中的某些新功能对其进行改进。

function coalesce() {
  $args = func_get_args();
  foreach ($args as $arg) {
    if (!empty($arg)) {
    return $arg;
    }
  }
  return $args[0];
}

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.