Is there a better PHP way for getting default valu

2019-01-16 23:34发布

问题:

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?

回答1:

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!



回答2:

Time passes and PHP is evolving. PHP7 now supports 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';


回答3:

use error control operator @ with PHP 5.3 shortcut version of ternary operator

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



回答4:

PHP 5.3 has a shortcut version of ternary operator:

$x = $foo ?: 'defaultvaluehere';

which is basically

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

Otherwise, no, there's no shorter method.



回答5:

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.



回答6:

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.



回答7:

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.