title: PHP - Create a new array using list of array keys in dot notation
body: <p>I'm in the process of building a REST API and all data is being returned as JSON. Each request is funneled through a single function that does the job of setting HTTP status codes, returning messages or data, setting headers, etc. I also allow users to add a <code>?fields=</code> parameter where they can specify what fields they want returned (e.g <code>?fields=id,hostnames,ip_addresses</code>), if the parameter is not present they of course get all the data returned. The function that does this is also part of the function mentioned earler that sets the headers/data/messages, etc. What I want to be able to do is allow the user to specify field names using dot notation so they can specify fields from something other than a top-level field. So for example, I have a structure like this:</p>
  
  <pre><code>{
      "id": "8a2b449111b449409c465c66254c6fcc",
      "hostnames": [
          "webapp1-sfo",
          "webapp1-sfo.example.com"
      ],
      "ip_addresses": [
          "12.26.16.10",
          "ee80::ae56:2dff:fd89:7868"
      ],
      "environment": "Production",
      "data_center": "sfo",
      "business_unit": "Operations",
      "hardware_type": "Server",
      "currently_in_maintenance": false,
      "history": [
          {
              "id": 58,
              "time_start_utc": "2013-01-27 00:40:00",
              "time_end_utc": "2013-01-27 01:45:00",
              "ticket_number": "CHG123456",
              "reason": "January production maintenance",
              "links": [
                  {
                      "rel": "self",
                      "link": "https://localhost/api/v1/maintenances/58"
                  }
              ]
          },
          {
              "id": 104,
              "time_start_utc": "2013-02-25 14:36:00",
              "time_end_utc": "2013-02-25 18:36:00",
              "ticket_number": "CHG456789",
              "reason": "February production maintenance",
              "links": [
                  {
                      "rel": "self",
                      "link": "https://localhost/api/v1/maintenances/104"
                  }
              ]
          },
          {
              "id": 143,
              "time_start_utc": "2013-03-17 00:30:00",
              "time_end_utc": "2013-03-17 01:55:00",
              "ticket_number": "CHG789123",
              "reason": "March production maintenance",
              "links": [
                  {
                      "rel": "self",
                      "link": "https://localhost/api/v1/maintenances/143"
                  }
              ]
          }
      ]
  }
  </code></pre>
  
  <p>Using this function, I can pull out top level fields (where <code>$mData</code> is the data structure above, and <code>$sParams</code> is the string of fields requested by the user):</p>
  
  <pre><code>private function removeFields($mData, $sParams){
      $clone = $mData;  // Clone the original data
      $fields = explode(',', $sParams);
  
      // Remove fields not requested by the user
  
      foreach($mData as $key =&gt; $value){
          if(!in_array((string)$key, $fields)){
              unset($mData[$key]);
          }
      }
  
      // If no fields remain, restore the original data
      // Chances are the user made a typo in the fields list
  
      if(count($mData) == 0){
          $mData = $clone;
      }
  
      return $mData;
  }
  </code></pre>
  
  <p>Note: <code>$sParams</code> comes in as a string and is what is provided by the user (comma separated list of fields they want to see).</p>
  
  <p>So <code>?fields=hostnames,history</code> would return:</p>
  
  <pre><code>{
      "hostnames": [
          "webapp1-sfo",
          "webapp1-sfo.example.com",
      ],
      "history": [
          {
              "id": 58,
              "time_start_utc": "2013-01-27 00:40:00",
              "time_end_utc": "2013-01-27 01:45:00",
              "ticket_number": "CHG123456",
              "reason": "January production maintenance",
              "links": [
                  {
                      "rel": "self",
                      "link": "https://localhost/api/v1/maintenances/58"
                  }
              ]
          },
          {
              "id": 104,
              "time_start_utc": "2013-02-25 14:36:00",
              "time_end_utc": "2013-02-25 18:36:00",
              "ticket_number": "CHG456789",
              "reason": "February production maintenance",
              "links": [
                  {
                      "rel": "self",
                      "link": "https://localhost/api/v1/maintenances/104"
                  }
              ]
          },
          {
              "id": 143,
              "time_start_utc": "2013-03-17 00:30:00",
              "time_end_utc": "2013-03-17 01:55:00",
              "ticket_number": "CHG789123",
              "reason": "March production maintenance",
              "links": [
                  {
                      "rel": "self",
                      "link": "https://localhost/api/v1/maintenances/143"
                  }
              ]
          }
      ]
  }
  </code></pre>
  
  <p>But if I want to return maybe just the <code>ticket_number</code> field from <code>history</code> I want the user to be able to do <code>?fields=history.ticket_number</code> or if they want the ticket number and link they could do this: <code>?fields=history.ticket_number,history.links.link</code>...which would return:</p>
  
  <pre><code>{
      "history": [
          {
              "ticket_number": "CHG123456",
              "links": [
                  {
                      "link": "https://localhost/api/v1/maintenances/58"
                  }
              ]
          },
          {
              "ticket_number": "CHG456789",
              "links": [
                  {
                      "link": "https://localhost/api/v1/maintenances/104"
                  }
              ]
          },
          {
              "ticket_number": "CHG789123",
              "links": [
                  {
                      "link": "https://localhost/api/v1/maintenances/143"
                  }
              ]
          }
      ]
  }
  </code></pre>
  
  <p>I've tried many different array access methods for dot notation from stack overflow but they all break when the value of <code>history</code> is a numeric array...so for instance, using the methods I've found online so far I would need to do something like this to achieve the same output above (which obviously is not good...especially when you have hundreds of records).</p>
  
  <p><code>?fields=history.0.ticket_number,history.0.links.0.link,history.1.ticket_number,history.1.links.0.link,history.2.ticket_number,history.2.links.0.link,</code></p>
  
  <p>I was also looking for something that was dynamic and recursive as each API endpoint returns a different data structure (for instance, when a collection is requested it returns a numeric array filled with associative arrays..or in json speak, an array of objects...and some of those objects may have arrays (numeric or associative)).</p>
  
  <p>Thanks in advance</p>
  
  <p>P.S. - I don't really care if the code creates a new data array containing the requested data or directly manipulates the original data (as it does in my removeFields() function).</p>
  
  <p>UPDATE: I've created a PHPFiddle that should hopefully show the issue I've been running into. <a href="http://phpfiddle.org/main/code/tw1i-qu7s" rel="nofollow">http://phpfiddle.org/main/code/tw1i-qu7s</a></p>