Search code examples
phparraysassociative-arraykey-valuedefaultdict

Default value for an associative array in PHP, if key not present


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

Solution

  • 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' );