Desde que uso MongoDB frente a MySQL me han ido surgiendo nuevos problemas a los que no me había enfrentado de forma común. Poder acceder a documentos que pueden tener una profundidad variable y tener que acceder a una serie de valores podía llegar a hacer que tuviese que montar mucho código para ciertas operaciones. Así que me creé un par de funcioncillas la mar de útiles.

El código mostrado aquí (que es fácil que salga mal) se puede acceder desde pastebin en la siguiente dirección: http://pastebin.com/sUQU8N8j

Nótese que la notación con ‘.’ es para simplificarlo todo sustancialmente pero puede introducir riesgos de acabar con una estructura no deseada si las claves no son estáticas (con valores especialmente introducidos por el usuario). Si se hace uso de whitelisting a la hora de aceptar parámetros del usuario, no debería haber problema.
Se puede hacer fácilmente una variante que en vez de tener como entrada una cadena, tenga un array que especifique las claves a acceder, evitando acceso indebido a más profunidad de la deseada.

Funciones:

function & access_value_dot($key, &$array) {  
    if (is_array($key)) {  
        $values = array();  
        foreach ($key as $single_key) $values[] = access_value_dot($single_key, $array);  
        return $values;  
    }  
    if (empty($key)) return $array;  
    $slices = explode('.', $key);  
    foreach ($slices as $slice) $array = &$array[$slice];  
    return $array;  
}  

function access_value_dot_set($key, &$array, $value) {  
    if (is_array($key)) {  
        $values = array();  
        $value = array_values($value);  
        foreach (array_values($key) as $k => $single_key) {  
            access_value_dot_set($single_key, $array, $value[$k]);  
        }  
        return;  
    }  
    $ref = &access_value_dot($key, $array);  
    $ref = $value;  
}  

Ejemplos:

public function testAccessValueDot() {  
    $data = array(  
        'level1' => array(  
            'level2b' => array(  
                'level3' => array(  
                    'level4a' => 1,  
                    'level4b' => 'Hello World',  
                ),  
            ),  
            'key' => 2,  
        ),  
        'level1a' => array(),  
    );  
    $this->assertEquals(access_value_dot('level1.level2b.level3.level4b', $data), 'Hello World');  
    $this->assertEquals(access_value_dot(  
        array(  
            'level1.level2b.level3.level4a',  
            'level1.level2b.level3.level4b',  
            'level1.key',  
            'level1a',  
            'level1.level2b.level3',  
        ), $data), array(  
            '1',  
            'Hello World',  
            '2',  
            array(),  
            array(  
            'level4a' => 1,  
            'level4b' => 'Hello World',  
        )  
    ));  
}  

public function testAccessValueDotSet() {  
    $object = (object)array(  
        'bbcode' => array(  
            'title' => 'Hello [b]World[/b]',  
            'descriptions' => array(  
                'short' => 'This is the [b]short[/b] description.',  
                'long' => 'This is the [b]LONG[/b] description.',  
            ),  
        ),  
        'html' => array(  
        ),  
    );  

    $field_keys = array(  
        'title',  
        'descriptions.short',  
        'descriptions.long',  
    );  

    // Accessing bbcode values.  
    $extracted_values = access_value_dot($field_keys, $object->bbcode);  

    {  
        // Converting bbcode to html.  
        $modified_values = array_map(function($value) {  
            return preg_replace_callback('@\\[(\\w+)\\](.*)\\[/\\1\\]@Umsi', function($captures) {  
                list(, $bbcode, $text) = $captures;  
                switch ($bbcode) {  
                    case 'b': return '<strong>' . $text . '</strong>';  
                    default: throw(new Exception("Unknown bbcode '{$bbcode}'"));  
                }  
            }, htmlspecialchars($value));  
        }, $extracted_values);  
    }  

    // Writting bbcode values.  
    access_value_dot_set($field_keys, $object->html, $modified_values);  

    $this->assertEquals(  
        $object->html,  
        array(  
            'title' => 'Hello <strong>World</strong>',  
            'descriptions' => array(  
                'short' => 'This is the <strong>short</strong> description.',  
                'long' => 'This is the <strong>LONG</strong> description.',  
            ),  
        )  
    );  
}