39 votes

Convertir la syntaxe à points comme "this.that.other" en un tableau multidimensionnel en PHP

Tout comme l'indique le titre, j'essaie de créer un analyseur syntaxique et d'essayer de trouver la solution optimale pour convertir quelque chose de l'espace de noms dot en un tableau multidimensionnel tel que

s1.t1.column.1 = size:33%

serait identique à

$source['s1']['t1']['column']['1'] = 'size:33%';

55voto

alex Points 186293

Essayez ce numéro...

function assignArrayByPath(&$arr, $path, $value, $separator='.') {
    $keys = explode($separator, $path);

    foreach ($keys as $key) {
        $arr = &$arr[$key];
    }

    $arr = $value;
}

CodePad

Cela va parcourir les clés (délimitées par . par défaut) pour arriver à la propriété finale, puis effectuer l'assignation sur la valeur.

Si certaines clés ne sont pas présentes, elles sont créées.

38voto

phaberest Points 1917

Pour votre information, dans Laravel, nous avons une fonction d'aide array_set() qui se traduit par cette fonction

Méthode pour stocker dans un tableau en utilisant la notation pointée

/**
 * Définit un élément de tableau à une valeur donnée en utilisant la notation "dot".
 *
 * Si aucune clé n'est donnée à la méthode, le tableau entier sera remplacé.
 *
 * @param  array   $array
 * @param  string  $key
 * @param  mixed   $value
 * @return array
 */
public static function set(&$array, $key, $value)
{
    if (is_null($key)) {
        return $array = $value;
    }

    $keys = explode('.', $key);

    while (count($keys) > 1) {
        $key = array_shift($keys);

        // Si la clé n'existe pas à cette profondeur, nous allons simplement créer un tableau vide
        // pour contenir la valeur suivante, ce qui nous permettra de créer les tableaux pour contenir les valeurs finales
        // à la profondeur correcte. Ensuite, nous continuerons à creuser dans le tableau.
        if (! isset($array[$key]) || ! is_array($array[$key])) {
            $array[$key] = [];
        }

        $array = &$array[$key];
    }

    $array[array_shift($keys)] = $value;

    return $array;
}

C'est aussi simple que

$array = ['products' => ['desk' => ['price' => 100]]];

array_set($array, 'products.desk.price', 200);

// ['products' => ['desk' => ['price' => 200]]]

Vous pouvez vérifier dans la documentation

Si vous devez plutôt obtenir les données en utilisant la notation pointée, le processus est un peu plus long, mais servi sur un plateau par array_get() qui se traduit par cette fonction (en fait, la source liée vous montre toutes les classes d'aide liées aux tableaux)

Méthode pour lire à partir d'un tableau en utilisant la notation pointée

/**
 * Obtenir un élément d'un tableau en utilisant la notation "dot".
 *
 * @param  \ArrayAccess|array  $array
 * @param  string  $key
 * @param  mixed   $default
 * @return mixed
 */
public static function get($array, $key, $default = null)
{
    if (! static::accessible($array)) {
        return value($default);
    }
    if (is_null($key)) {
        return $array;
    }
    if (static::exists($array, $key)) {
        return $array[$key];
    }
    if (strpos($key, '.') === false) {
        return $array[$key] ?? value($default);
    }
    foreach (explode('.', $key) as $segment) {
        if (static::accessible($array) && static::exists($array, $segment)) {
            $array = $array[$segment];
        } else {
            return value($default);
        }
    }
    return $array;
}

Comme vous pouvez le voir, il utilise deux sous-méthodes, accessible() et exists()

/**
 * Déterminer si la valeur donnée est accessible comme un tableau.
 *
 * @param  mixed  $value
 * @return bool
 */
public static function accessible($value)
{
    return is_array($value) || $value instanceof ArrayAccess;
}

Et

/**
 * Déterminer si la clé donnée existe dans le tableau fourni.
 *
 * @param  \ArrayAccess|array  $array
 * @param  string|int  $key
 * @return bool
 */
public static function exists($array, $key)
{
    if ($array instanceof ArrayAccess) {
        return $array->offsetExists($key);
    }
    return array_key_exists($key, $array);
}

La dernière chose qu'il utilise, mais que vous pouvez probablement ignorer, est value() qui est

if (! function_exists('value')) {
    /**
     * Retourne la valeur par défaut de la valeur donnée.
     *
     * @param  mixed  $value
     * @return mixed
     */
    function value($value)
    {
        return $value instanceof Closure ? $value() : $value;
    }
}

2voto

Erkin Eren Points 21

Vous pouvez utiliser cette fonction pour convertir un tableau de notation avec des points en un tableau multidimensionnel.

function flattenToMultiDimensional(array $array, $delimiter = '.')
{
    $result = [];
    foreach ($array as $notations => $value) {
        // extraire les clés
        $keys = explode($delimiter, $notations);
        // inverser les clés pour les affectations
        $keys = array_reverse($keys);

        // définir la valeur initiale
        $lastVal = $value;
        foreach ($keys as $key) {
            // envelopper la valeur avec la clé à chaque itération
            $lastVal = [
                $key => $lastVal
            ];
        }

        // fusionner le résultat
        $result = array_merge_recursive($result, $lastVal);
    }

    return $result;
}

Example:

$array = [
    'test.example.key' => 'value'
];

print_r(flattenToMultiDimensional($array));

Output:

Array
(
    [test] => Array
        (
            [example] => Array
                (
                    [key] => value
                )

        )

)

1voto

grasmash Points 79

Je vous suggère d'utiliser dflydev/dot-access-data.

Si vous n'êtes pas familier avec l'utilisation de Composer, rendez-vous sur https://getcomposer.org/ pour une introduction afin de pouvoir télécharger et charger automatiquement le package en tant que dépendance pour votre projet.

Une fois que vous avez le package, vous pouvez charger un tableau multi-dimensionnel dans un objet Data :

use Dflydev\DotAccessData\Data;

$data = new Data(array(
  's1' => array(
    't1' => array(
      'column' => array(
        '1' => 'size:33%',
      ),
    ),
  ),
);

Et accéder aux valeurs en utilisant la notation pointée :

$size = $username = $data->get('s1.t1.column.1');

0voto

Yann Charlou Points 1

Vous devriez essayer celui-ci : https://symfony.com/doc/current/components/property_access.html

Cela vous permet d'accéder à tout comme des tableaux, des objets, des setters, des getters, etc... avec la notation en point.

Vous pouvez l'utiliser en standalone sans symfony. Si votre projet utilise composer, c'est une installation en une seule ligne.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X