11
\$\begingroup\$

I feel like I write this a lot in PHP:

 $val = isset($var['foo']) ? $var['foo'] : '';

Is there a shorter way to write this? I can't use the ternary operator because the conditional is an isset check, not the value of the function itself.

\$\endgroup\$
2
  • \$\begingroup\$ I toyed around with using filter_var() but that isn't any shorter really. Never got around to doing speed test on it. Benjamin's answer is your best bet. \$\endgroup\$
    – mseancole
    Commented Jun 19, 2012 at 13:42
  • \$\begingroup\$ The most simple way is merely $val = @$var['foo'];. You may look at my previous answer at a similar question for detailed explanation. \$\endgroup\$
    – cFreed
    Commented Jul 27, 2015 at 20:52

5 Answers 5

7
\$\begingroup\$

You could wrap it in a function (check the syntax, I don't actually know PHP):

function getDefault($array, $key, $default) {
    return isset($array[$key]) ? $array[$key] : $default;
}
\$\endgroup\$
1
  • 2
    \$\begingroup\$ Was just about to post that! :) (And your syntax is correct, though I would probably do function getDefault(array $array, $key, $default). \$\endgroup\$
    – Corbin
    Commented Jun 19, 2012 at 6:11
14
\$\begingroup\$

Now three years later we have the Null Coalesce Operator in PHP7:

 $val = $var['foo'] ?? '';

http://3v4l.org/Kcb2A

\$\endgroup\$
2
  • \$\begingroup\$ That's awesome! About time ;) I wonder how long it's going to take for most servers to get updated to PHP7 and have it be the main standard at least people on shared hosts. Time for me to look into updating my system. \$\endgroup\$
    – CTS_AE
    Commented Aug 16, 2015 at 21:07
  • 1
    \$\begingroup\$ Note that it is still in beta phase (currently beta 3). \$\endgroup\$
    – PeeHaa
    Commented Aug 17, 2015 at 7:13
6
\$\begingroup\$

Building off of what Benjamin Kloster has

If you pass the parameter by reference instead of value it will not choke trying to pass in an invalid index.

function getDefault(&$isset, $default) {
    return isset($isset) ? $isset : $default;
}

Or if you want a dynamic amount of parameters to default to

Just don't pass in any unknown indexes for them because I'm not sure how to do dynamic parameters as reference if that's even possible

ie: getDefault("default", $notSet, $stillNotSet, "isSet");

function getDefault($default, &$isset)
{
    $argCount = func_num_args();
    if ($argCount < 3)
        return isset($isset) ? $isset : $default;
    else
    {
        for($i = 0; $i < $argCount; $i++)
        {
            $arg = func_get_arg($i);
            if (isset($arg))
                return $arg;
        }
        return $default;
    }
}
\$\endgroup\$
7
  • \$\begingroup\$ Return is missing in else statement. Why do you start loop from 2nd argument? \$\endgroup\$
    – pronebird
    Commented Aug 16, 2015 at 10:12
  • \$\begingroup\$ @Andy that's a good point I'm sure my updated code would include that so I will update this answer to include that; good catch : ) It's been a while since I wrote this so I'm not sure if I had a reason but that's also a good catch I will update ; ) \$\endgroup\$
    – CTS_AE
    Commented Aug 16, 2015 at 20:53
  • \$\begingroup\$ Too bad this won't work for multiple arguments. it throws a notice when calling getDefault with bunch of non-existing variables, apparently because only the first argument is passed by ref. \$\endgroup\$
    – pronebird
    Commented Aug 16, 2015 at 20:55
  • \$\begingroup\$ @Andy unfortunately there's no way to pass any given amount of parameters all as reference from what my last research concluded. \$\endgroup\$
    – CTS_AE
    Commented Aug 16, 2015 at 20:57
  • \$\begingroup\$ You can drop else statement completely and just leave isset($isset) ? $isset : $default;. PHP 7 solves that disaster with ?? operator. \$\endgroup\$
    – pronebird
    Commented Aug 16, 2015 at 20:59
2
\$\begingroup\$

Another approach is

$foo = ''; // default value
extract($var); // extracts all array items to corresponding variables

This is not appropriate in all cases, eg. when:

  • You don't want to extract all array elements, just one
  • You want to extract the variable to a different name (it's possible to specify a prefix though, so the item will extract to $prefix_foo)
  • You don't want to pollute your name space

But in other cases it's quite neat and clean.

\$\endgroup\$
1
\$\begingroup\$

If you want something fancier that supports nested structures, like such:

$foo = json_decode('{"bar":[42]}');
echo getDefault( $foo, '-default-', 'bar', 0 );
# 42
echo getDefault( $foo, '-default-', 'bar', 1 );
# -default-
echo getDefault( $foo, '-default-', 'missing' );
# -default-

... consider:

function getDefault( $container, $default /*, key1, key2 */ ) {
    // get all remaining arguments
    $keys = array_slice( func_get_args(), 2 );

    while( $keys ) {
        $key = array_shift( $keys );
        if( is_array( $container ) && isset( $container[ $key ] ) ) {
            $container = $container[ $key ];
        } else if( is_object( $container ) && isset( $container->$key ) ) {
            $container = $container->$key;
        } else {
            return $default;
        }
    }

    return $container;
}
\$\endgroup\$

Not the answer you're looking for? Browse other questions tagged or ask your own question.