mikl
mikl

Reputation: 24267

Coalesce function for PHP?

Many programming languages have a coalesce function (returns the first non-NULL value, example). PHP, sadly in 2009, does not.

What would be a good way to implement one in PHP until PHP itself gets a coalesce function?

Upvotes: 140

Views: 76424

Answers (10)

tim
tim

Reputation: 2724

A function to return the first non-NULL value:

  function coalesce(&...$args) { // ... as of PHP 5.6
    foreach ($args as $arg) {
      if (isset($arg)) return $arg;
    }
  }

Equivalent to $var1 ?? $var2 ?? null in PHP 7+.

A function to return the first non-empty value:

  function coalesce(&...$args) {
    foreach ($args as $arg) {
      if (!empty($arg)) return $arg;
    }
  }

Equivalent to (isset($var1) ? $var1 : null) ?: (isset($var2) ? $var2 : null) ?: null in PHP 5.3+.

The above will consider a numerical string of "0.00" as non-empty. Typically coming from a HTTP GET, HTTP POST, browser cookie or the MySQL driver passing a float or decimal as numerical string.

A function to return the first variable that is not undefined, null, (bool)false, (int)0, (float)0.00, (string)"", (string)"0", (string)"0.00", (array)[]:

  function coalesce(&...$args) {
    foreach ($args as $arg) {
      if (!empty($arg) && (!is_numeric($arg) || (float)$arg!= 0)) return $arg;
    }
  }

To be used like:

$myvar = coalesce($var1, $var2, $var3, ...);

Upvotes: 0

Madbreaks
Madbreaks

Reputation: 19539

I'm expanding on the answer posted by Ethan Kent. That answer will discard non-null arguments that evaluate to false due to the inner workings of array_filter, which isn't what a coalesce function typically does. For example:

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

Oops

To overcome this, a second argument and function definition are required. The callable function is responsible for telling array_filter whether or not to add the current array value to the result array:

// "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'));
}

It would be nice if you could simply pass isset or 'isset' as the 2nd argument to array_filter, but no such luck.

Upvotes: 2

flori
flori

Reputation: 15837

PHP 7 introduced a real coalesce operator:

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

If the value before the ?? does not exists or is null the value after the ?? is taken.

The improvement over the mentioned ?: operator is, that the ?? also handles undefined variables without throwing an E_NOTICE.

Upvotes: 75

Paulo Freitas
Paulo Freitas

Reputation: 13649

PHP 5.3+, with closures:

function coalesce()
{
    return array_shift(array_filter(func_get_args(), function ($value) {
        return !is_null($value);
    }));
}

Demo: https://eval.in/187365

Upvotes: 0

Andrew
Andrew

Reputation: 2114

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.

Upvotes: 10

Ethan Kent
Ethan Kent

Reputation: 281

I really like the ?: operator. Unfortunately, it is not yet implemented on my production environment. So I use the equivalent of this:

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

Upvotes: 19

Kevin
Kevin

Reputation: 13087

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

Upvotes: 203

Peter Bailey
Peter Bailey

Reputation: 105878

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.

Upvotes: 6

mikl
mikl

Reputation: 24267

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];
}

Upvotes: 0

Will Shaver
Will Shaver

Reputation: 13081

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

Upvotes: 30

Related Questions