From PHP 5.3 we can use some amazing new interfaces so magical. One of them is ArrayAccess. This interface provides a set of methods that we can use to implement the array behavior in a stdClass. Let’s see an example:

<?php

class Options implements ArrayAccess {
  
  private $items = [
    'item-1' => 'value 1',
    'item-2' => [
      'sub-item-2' => 'value 2'
    ]
  ];
  
  public function offsetSet($offset, $value) 
  {
    if (is_null($offset)) {
      $this->items[] = $value;
    } else {
      $this->items[$offset] = $value;
    }
  }

  public function offsetExists($offset) 
  {
    return isset($this->items[$offset]);
  }

  public function offsetUnset($offset) 
  {
    unset($this->items[$offset]);
  }

  public function offsetGet($offset) 
  {
    return isset($this->items[$offset]) ? $this->items[$offset] : null;
  }
  
  public function __get( $name )
  {
    $name = str_replace('_', '-', $name );
    
    if( isset( $this->items[$name] ) ) {
      return $this->items[$name];
    }
  }
}

How does it work? In the example above, I’ve already loaded some items in the internal array. Let’s what we can do:

<?php

// let create the instance
$a = new Options;

// now, we can use this instance like an array
var_dump( $a['item-1'] );
var_dump( $a['item-2']['sub-item-2'] );

// also, we can get the value of internal array by property
var_dump( $a->item_1 );

// we can set the value 
$a['item-1'] = "my new value";
var_dump( $a['item-1'] );

Next, we can add the __set() magic method as well:

...

  public function __set( $name, $value )
  {
    $name = str_replace('_', '-', $name );
    
    $this->offsetSet( $name, $value );
  }

and then:

<?php 

// we can set the value 
$a->item_1 = "by property";
var_dump( $a['item-1'] );