title: Access a multidimensional array with dot notation
body: <p>I am looking to write a class which will be able to access multidimensional arrays with dot notation:</p>
  
  <pre><code>$config-&gt;get('bar.baz.foo');
  </code></pre>
  
  <p>Instead of:</p>
  
  <pre><code>$config['bar']['baz']['foo']
  </code></pre>
  
  <p>This is the class:</p>
  
  <pre><code>&lt;?php
  
  class DotNotation
  {
      /**
       * @var array
       */
      protected $values = array();
  
      public function __construct(array $values)
      {
          $this-&gt;values = $values;
      }
  
      /**
       * @param string $path
       * @param string $default
       * @return mixed
       */
      public function get($path, $default = null)
      {
          $array = $this-&gt;values;
  
          if (!empty($path)) {
              $keys = explode('.', $path);
              foreach ($keys as $key) {
                  if (isset($array[$key])) {
                      $array = $array[$key];
                  } else {
                      return $default;
                  }
              }
          }
  
          return $array;
      }
  
      /**
       * @param string $path
       * @param mixed $value
       */
      public function set($path, $value)
      {
          $link = &amp; $this-&gt;values;
  
          if (!empty($path)) {
              $keys = explode('.', $path);
              foreach ($keys as $key) {
  
                  if (!isset($link[$key])) {
                      $link[$key] = array();
                  }
  
                  if (!is_array($link[$key])) {
                      throw new \RuntimeException("Can not set value for `$key` in `$path` path because it is not array.");
                  }
  
                  $link = &amp; $link[$key];
              }
          }
  
          $link = $value;
      }
  
      /**
       * @param $path
       * @param array $values
       */
      public function add($path, array $values)
      {
          $get = (array)$this-&gt;get($path);
          $this-&gt;set($path, $this-&gt;arrayMergeRecursiveDistinct($get, $values));
      }
  
      /**
       * @param mixed $parameters
       */
      public function merge($parameters)
      {
          $this-&gt;add(null, (array)$parameters);
      }
  
      /**
       * @param string $path
       * @return bool
       */
      public function have($path)
      {
          $keys = explode('.', $path);
          $array = $this-&gt;values;
          foreach ($keys as $key) {
              if (isset($array[$key])) {
                  $array = $array[$key];
              } else {
                  return false;
              }
          }
  
          return true;
      }
  
      /**
       * array_merge_recursive does indeed merge arrays, but it converts values with duplicate
       * keys to arrays rather than overwriting the value in the first array with the duplicate
       * value in the second array, as array_merge does. I.e., with array_merge_recursive,
       * this happens (documented behavior):
       *
       * array_merge_recursive(array('key' =&gt; 'org value'), array('key' =&gt; 'new value'));
       *     =&gt; array('key' =&gt; array('org value', 'new value'));
       *
       * arrayMergeRecursiveDistinct does not change the datatypes of the values in the arrays.
       * Matching keys' values in the second array overwrite those in the first array, as is the
       * case with array_merge, i.e.:
       *
       * arrayMergeRecursiveDistinct(array('key' =&gt; 'org value'), array('key' =&gt; 'new value'));
       *     =&gt; array('key' =&gt; array('new value'));
       *
       * Parameters are passed by reference, though only for performance reasons. They're not
       * altered by this function.
       *
       * If key is integer, it will be merged like array_merge do:
       * arrayMergeRecursiveDistinct(array(0 =&gt; 'org value'), array(0 =&gt; 'new value'));
       *     =&gt; array(0 =&gt; 'org value', 1 =&gt; 'new value');
       *
       * @param array $array1
       * @param array $array2
       * @return array
       * @author Daniel &lt;daniel (at) danielsmedegaardbuus (dot) dk&gt;
       * @author Gabriel Sobrinho &lt;gabriel (dot) sobrinho (at) gmail (dot) com&gt;
       * @author Anton Medvedev &lt;anton (at) elfet (dot) ru&gt;
       */
      protected function arrayMergeRecursiveDistinct(array &amp;$array1, array &amp;$array2)
      {
          $merged = $array1;
  
          foreach ($array2 as $key =&gt; &amp;$value) {
              if (is_array($value) &amp;&amp; isset ($merged[$key]) &amp;&amp; is_array($merged[$key])) {
                  if (is_int($key)) {
                      $merged[] = $this-&gt;arrayMergeRecursiveDistinct($merged[$key], $value);
                  } else {
                      $merged[$key] = $this-&gt;arrayMergeRecursiveDistinct($merged[$key], $value);
                  }
              } else {
                  if (is_int($key)) {
                      $merged[] = $value;
                  } else {
                      $merged[$key] = $value;
                  }
              }
          }
  
          return $merged;
      }
  }
  </code></pre>
  
  <p>How can I improve this class to not use <code>explode</code>?</p>