Note: I have already read Function to set default value of associative array if the key is not present and Default values for Associative array in PHP.
Let's say:
$a = array('foo' => '123');
$b = $a['bar']; // PHP Notice: Undefined index: bar
I'd like to have an empty string by default ""
if the key is not present, instead of a PHP Notice.
I know the solutions would be to do:
$b = isset($a['bar']) ? $a['bar'] : "";
// or, since PHP 5.3:
$b = $a['bar'] ?: ""; // but this still produces a "PHP Notice"!
Is there a way to avoid the ?: ""
and directly have:
$b = $a['bar'];
get ""
with no Notice?
Note: this exists in Python with:
import collections
d = collections.defaultdict(str)
print(d['bar']) # empty string, no error
CodePudding user response:
No. PHP arrays don't work that way.
What you can do to achieve a similar simplicity is use a class. Then you can write,
$a = new FakeArray([ 'foo' => '123' ]);
$a->setDefault('baz');
$b = $a->bar; // $b is now 'baz'.
$c = $a->foo; // $c is now '123'.
and have $a
return a default value of your choice using a magic getter.
I would have thought that extending ArrayObject
would have come very close to what you wanted:
class FakeArray extends ArrayObject {
...
public function __get($key) {
return $this->default;
}
}
but while $a['foo'] = 'bar'
does store the value, actually even accessing a nonexistent property now triggers an Index notice:
$b = $a->baz;
PHP Notice: Undefined index: baz in ./test.php ...
So, the ArrayObject
actually behaves worse than a StdClass.
CodePudding user response:
I'd like to submit another solution using array ArrayObject
as stated above
This extends the class and slightly tweaks the offsetGet
behavior to always return an empty string
the parent::
statement here invokes the function of the extended class
class MyArrayObject extends ArrayObject
{
function offsetGet( $key )
{
return parent::offsetExists( $key ) ? parent::offsetGet( $key ) : '';
}
}
$myArray = new MyArrayObject( array( 'foo' => '123') );
var_dump( $myArray['foo'] ); // '123' provided string
var_dump( $myArray['bar'] ); // '' our new default
var_dump( isset( $myArray['foo'] ) ); // true
var_dump( isset( $myArray['bar'] ) ); // false
foreach( $myArray as $key )
{
var_dump( $key ); // only one iteration of '123'
}
var_dump( is_array( $myArray ) ); // false unfortunately
var_dump( is_iterable( $myArray ) ); // true however
var_dump( array_merge( array(), $myArray ) ); // will fail
var_dump( array_merge( array(), (array) $myArray ) ); // will work
and finally
$myArray['bar'] = '456'; // now if we set bar
var_dump( $myArray['bar'] ); // '456' new value
var_dump( isset( $myArray['bar'] ) ); // now true
as a suggestion from @miken32 to set a default value
class MyArrayObject extends ArrayObject
{
protected $default;
public function __construct($array = [], $default = null, $flags = 0, $iteratorClass = "ArrayIterator")
{
parent::__construct( $array, $flags, $iteratorClass );
$this->default = $default;
}
function offsetGet( $key )
{
return parent::offsetExists( $key ) ? parent::offsetGet( $key ) : $this->default;
}
}
you can set a default value via
$myArray = new MyArrayObject( array( 'foo' => '123'), 'mydefault' );
CodePudding user response:
You'd have to pre-populate your array with your defaults or create a object class as stated to handle the default response.
$array = array('foo' => '123') array('foo' => '', 'bar' => '');
var_dump( $array );
array(2) {
["foo"]=>string(3) "123"
["bar"]=> string(0) ""
}
CodePudding user response:
1 step - add this function:
function getIfIsset(array $array, string $key)
{
return $array[$key] ?? '';
}
2 step - use this:
echo getIfIsset($mayArray, 'bar');
CodePudding user response:
You can use this method @ before variable with key:
echo @$a['bar'];