Usar una ruta de cadena para configurar datos de matriz anidados [duplicado]

Resuelto Anthony asked hace 54 años • 8 respuestas

Tengo un caso de uso inusual para el que estoy intentando codificar. El objetivo es este: quiero que el cliente pueda proporcionar una cadena, como por ejemplo:

"cars.honda.civic = On"

Usando esta cadena, mi código establecerá un valor de la siguiente manera:

$data['cars']['honda']['civic'] = 'On';

Es bastante fácil tokenizar la entrada del cliente como tal:

$token = explode("=",$input);
$value = trim($token[1]);
$path = trim($token[0]);
$exploded_path = explode(".",$path);

Pero ahora, ¿cómo uso la ruta $exploded para configurar la matriz sin hacer algo desagradable como una evaluación?

Anthony avatar Jan 01 '70 08:01 Anthony
Aceptado

Utilice el operador de referencia para obtener las sucesivas matrices existentes:

$temp = &$data;
foreach($exploded as $key) {
    $temp = &$temp[$key];
}
$temp = $value;
unset($temp);
alexisdm avatar Mar 09 '2012 02:03 alexisdm

Basado en la respuesta de alexisdm :

/**
 * Sets a value in a nested array based on path
 * See https://stackoverflow.com/a/9628276/419887
 *
 * @param array $array The array to modify
 * @param string $path The path in the array
 * @param mixed $value The value to set
 * @param string $delimiter The separator for the path
 * @return The previous value
 */
function set_nested_array_value(&$array, $path, &$value, $delimiter = '/') {
    $pathParts = explode($delimiter, $path);

    $current = &$array;
    foreach($pathParts as $key) {
        $current = &$current[$key];
    }

    $backup = $current;
    $current = $value;

    return $backup;
}
Ugo Méda avatar Jan 08 '2015 13:01 Ugo Méda

Código bien probado y 100% funcional. Establecer, obtener y desarmar valores de una matriz usando "padres". Los padres pueden ser cualquiera array('path', 'to', 'value')o una cadena path.to.value. Basado en el código de Drupal

 /**
 * @param array $array
 * @param array|string $parents
 * @param string $glue
 * @return mixed
 */
function array_get_value(array &$array, $parents, $glue = '.')
{
    if (!is_array($parents)) {
        $parents = explode($glue, $parents);
    }

    $ref = &$array;

    foreach ((array) $parents as $parent) {
        if (is_array($ref) && array_key_exists($parent, $ref)) {
            $ref = &$ref[$parent];
        } else {
            return null;
        }
    }
    return $ref;
}

/**
 * @param array $array
 * @param array|string $parents
 * @param mixed $value
 * @param string $glue
 */
function array_set_value(array &$array, $parents, $value, $glue = '.')
{
    if (!is_array($parents)) {
        $parents = explode($glue, (string) $parents);
    }

    $ref = &$array;

    foreach ($parents as $parent) {
        if (isset($ref) && !is_array($ref)) {
            $ref = array();
        }

        $ref = &$ref[$parent];
    }

    $ref = $value;
}

/**
 * @param array $array
 * @param array|string $parents
 * @param string $glue
 */
function array_unset_value(&$array, $parents, $glue = '.')
{
    if (!is_array($parents)) {
        $parents = explode($glue, $parents);
    }

    $key = array_shift($parents);

    if (empty($parents)) {
        unset($array[$key]);
    } else {
        array_unset_value($array[$key], $parents);
    }
}
ymakux avatar May 25 '2017 20:05 ymakux
$data = $value;
foreach (array_reverse($exploded_path) as $key) {
    $data = array($key => $data);
}
deceze avatar Mar 09 '2012 02:03 deceze