views:

1959

answers:

5

Many programming languages has a coalesce function (example). PHP, sadly, does not.

What would be the most efficient way to implement one in PHP?

+6  A: 

First hit for "php coalesce" on google.

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

http://drupial.com/content/php-coalesce

Will Shaver
Save a tiny bit of ram and don't duplicate the args into an array, just do foreach(func_get_args() as $arg) {}
TravisO
@TravisO I believe that caching func_get_args() is faster because it will save data in variable instead of calculating for every loop
Alfred
@TravisO yeah like Alfred said, if you bring the call to func_get_args() into the loop condition it'll get called each time - PHP can't tell that the function result won't change each time.
Ciaran McNulty
@[Alfred,Ciaran] - you are incorrect. foreach() evaluates the first argument only once, to get an array, and then iterates over it.
gahooa
Putting func_get_args() inside the foreach (here as $arg) won't change anything from a performance point of view.
Savageman
@Savageman ... exactly ... if you are thinking of squeezing this millisecond of performance or few bytes of memory out of your application you're probably looking at the wrong performance/memory bottleneck
ChrisR
A: 

I'm currently using this, but I wonder if it couldn't be improved with some of the new features in PHP 5.

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

Make sure you identify exactly how you want this function to work with certain types. PHP has a wide variety of type-checking or similar functions, so make sure you know how they work. This is an example comparison of is_null() and 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>';
}

As you can see, empty() returns true for all of these, but is_null() only does so for 2 of them.

Peter Bailey
+9  A: 

There is a new operator in php 5.3 which does this: ?:

// A
echo 'A' ?: 'B';

// B
echo '' ?: 'B';

// B
echo false ?: 'B';

// B
echo null ?: 'B';

Source: http://www.php.net/ChangeLog-5.php#5.3.0

Kevin
What about multiple ternary shortcuts, would something like "echo $a ?: $b ?: $c ?: $d;" work?
ChrisR
I just tested this and it does indeed work. Good suggestion.
Kevin
A: 

It is worth noting that due to PHP's treatment of uninitalised variables and array indices, any kind of coalesce function is of limited use. I would love to be able to do this:

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

But this will, in most cases, cause PHP to error with an E_NOTICE. The only safe way to test the existence of a variable before using it is to use it directly in empty() or isset(). The ternary operator suggested by Kevin is the best option if you know that all the options in your coalesce are known to be initialised.

Andrew