开发者

Is there a better PHP way for getting default value by key from array (dictionary)?

开发者 https://www.devze.com 2023-03-20 14:06 出处:网络
In Python one can do: foo = {} assert foo.get(\'bar\', \'开发者_运维技巧baz\') == \'baz\' In PHP one can go for a trinary operator as in:

In Python one can do:

foo = {}
assert foo.get('bar', '开发者_运维技巧baz') == 'baz'

In PHP one can go for a trinary operator as in:

$foo = array();
assert( (isset($foo['bar'])) ? $foo['bar'] : 'baz' == 'baz' );

I am looking for a golf version. Can I do it shorter/better in PHP?

UPDATE [March 2020]:

assert($foo['bar'] ?? 'baz' == 'baz');

It seems that Null coalescing operator ?? is worth checking out today.

found in the comments below (+1)


Time passes and PHP is evolving. PHP 7 now supports the null coalescing operator, ??:

// Fetches the value of $_GET['user'] and returns 'nobody'
// if it does not exist.
$username = $_GET['user'] ?? 'nobody';
// This is equivalent to:
$username = isset($_GET['user']) ? $_GET['user'] : 'nobody';

// Coalescing can be chained: this will return the first
// defined value out of $_GET['user'], $_POST['user'], and
// 'nobody'.
$username = $_GET['user'] ?? $_POST['user'] ?? 'nobody';


I just came up with this little helper function:

function get(&$var, $default=null) {
    return isset($var) ? $var : $default;
}

Not only does this work for dictionaries, but for all kind of variables:

$test = array('foo'=>'bar');
get($test['foo'],'nope'); // bar
get($test['baz'],'nope'); // nope
get($test['spam']['eggs'],'nope'); // nope
get($undefined,'nope'); // nope

Passing a previously undefined variable per reference doesn't cause a NOTICE error. Instead, passing $var by reference will define it and set it to null. The default value will also be returned if the passed variable is null. Also note the implicitly generated array in the spam/eggs example:

json_encode($test); // {"foo":"bar","baz":null,"spam":{"eggs":null}}
$undefined===null; // true (got defined by passing it to get)
isset($undefined) // false
get($undefined,'nope'); // nope

Note that even though $var is passed by reference, the result of get($var) will be a copy of $var, not a reference. I hope this helps!


Use the error control operator @ with the PHP 5.3 shortcut version of the ternary operator:

$bar = @$foo['bar'] ?: 'defaultvalue';


I find it useful to create a function like so:

function array_value($array, $key, $default_value = null) {
    return is_array($array) && array_key_exists($key, $array) ? $array[$key] : $default_value;
}

And use it like this:

$params = array('code' => 7777, 'name' => "Cloud Strife"); 

$code    = array_value($params, 'code');
$name    = array_value($params, 'name');
$weapon  = array_value($params, 'weapon', "Buster Sword");
$materia = array_value($params, 'materia');

echo "{ code: $code, name: $name, weapon: $weapon, materia: $materia }";

The default value in this case is null, but you may set it to whatever you need.

I hope it is useful.


PHP 5.3 has a shortcut version of the ternary operator:

$x = $foo ?: 'defaultvaluehere';

which is basically

if (isset($foo)) {
   $x = $foo;
else {
   $x = 'defaultvaluehere';
}

Otherwise, no, there's no shorter method.


A "slightly" hacky way to do it:

<?php
    $foo = array();
    var_dump('baz' == $tmp = &$foo['bar']);
    $foo['bar'] = 'baz';
    var_dump('baz' == $tmp = &$foo['bar']);

http://codepad.viper-7.com/flXHCH

Obviously this isn't really the nice way to do it. But it is handy in other situations. E.g. I often declare shortcuts to GET and POST variables like that:

<?php
    $name =& $_GET['name'];
    // instead of
    $name = isset($_GET['name']) ? $_GET['name'] : null;

PS: One could call this the "built-in ==$_=& special comparison operator":

<?php
    var_dump('baz' ==$_=& $foo['bar']);

PPS: Well, you could obviously just use

<?php
    var_dump('baz' == @$foo['bar']);

but that's even worse than the ==$_=& operator. People don't like the error suppression operator much, you know.


If you enumerate the default values by key in an array, it can be done this way:

$foo = array('a' => 1, 'b' => 2);
$defaults = array('b' => 55, 'c' => 44);

$foo = array_merge($defaults, $foo);

print_r($foo);

Which results in:

Array
(
    [b] => 2
    [c] => 44
    [a] => 1
)

The more key/value pairs that you enumerate defaults for, the better the code-golf becomes.


There was a solution proposed by "Marc B" to use ternary shortcut $x = $foo ?: 'defaultvaluehere'; but it still gives notices. Probably it's a mistyping, maybe he meant ?? or it were written before PHP 7 release. According to Ternary description:

Since PHP 5.3, it is possible to leave out the middle part of the ternary operator. Expression expr1 ?: expr3 returns expr1 if expr1 evaluates to TRUE, and expr3 otherwise.

But it doesn't use isset inside and produces notices. To avoid notices better to use Null Coalescing Operator ?? which uses isset inside it. Available in PHP 7.

The expression (expr1) ?? (expr2) evaluates to expr2 if expr1 is NULL, and expr1 otherwise. In particular, this operator does not emit a notice if the left-hand side value does not exist, just like isset(). This is especially useful on array keys.

Example #5 Assigning a default value

<?php
// Example usage for: Null Coalesce Operator
$action = $_POST['action'] ?? 'default';

// The above is identical to this if/else statement
if (isset($_POST['action'])) {
    $action = $_POST['action'];
} else {
    $action = 'default';
}

?>
0

精彩评论

暂无评论...
验证码 换一张
取 消