Konvertieren von Punktsyntax wie “this.that.other” in mehrdimensionales Array in PHP

Genau wie der Titel andeutet, versuche ich einen Parser zu erstellen und zu versuchen, die optimale Lösung zu finden, um etwas vom Punktnamensraum in ein mehrdimensionales Array zu konvertieren, so dass

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

wäre das Gleiche wie

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

   

Probieren Sie diese Nummer …

 function assignArrayByPath(&$arr, $path, $value, $separator='.') { $keys = explode($separator, $path); foreach ($keys as $key) { $arr = &$arr[$key]; } $arr = $value; } 

CodePad

Es durchläuft die Schlüssel (standardmäßig mit . Begrenzt), um zur endgültigen Eigenschaft zu gelangen, und führt dann eine Zuweisung für den Wert durch.

Wenn einige der Schlüssel nicht vorhanden sind, werden sie erstellt.

FYI In Laravel haben wir eine array_set() die in dieser function übersetzt

Methode zum Speichern in einem Array mit Punktnotation

 /** * Set an array item to a given value using "dot" notation. * * If no key is given to the method, the entire array will be replaced. * * @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); // If the key doesn't exist at this depth, we will just create an empty array // to hold the next value, allowing us to create the arrays to hold final // values at the correct depth. Then we'll keep digging into the array. if (! isset($array[$key]) || ! is_array($array[$key])) { $array[$key] = []; } $array = &$array[$key]; } $array[array_shift($keys)] = $value; return $array; } 

Es ist einfach wie

 $array = ['products' => ['desk' => ['price' => 100]]]; array_set($array, 'products.desk.price', 200); // ['products' => ['desk' => ['price' => 200]]] 

Sie können es in den Dokumenten überprüfen

Wenn Sie stattdessen die Daten mithilfe der Punktnotation array_get() müssen, ist der process ein wenig länger, wird aber auf einer Platte von array_get() was zu dieser function führt (die verknüpfte Quelle zeigt Ihnen tatsächlich alle mit dem Helferfeld verbundenen classn).

Methode zum Lesen von einem Array mit Punktnotation

 /** * Get an item from an array using "dot" notation. * * @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; } 

Wie Sie sehen können, verwendet es zwei Submethoden, accessible() und exists()

 /** * Determine whether the given value is array accessible. * * @param mixed $value * @return bool */ public static function accessible($value) { return is_array($value) || $value instanceof ArrayAccess; } 

Und

 /** * Determine if the given key exists in the provided array. * * @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); } 

Ich würde vorschlagen, dflydev / dot-access-Daten zu verwenden .

Wenn Sie mit der Verwendung von Composer nicht vertraut sind, gehen Sie zu https://getcomposer.org/, um eine Einführung zu erhalten, damit Sie das Paket herunterladen und automatisch laden können, und zwar als Abhängigkeit für Ihr Projekt.

Sobald Sie das Paket haben, können Sie ein mehrdimensionales Array in ein Data-Objekt laden:

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

Und greifen Sie auf die Werte mit Punktnotation zu:

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

Obwohl die Datei “passse_ini_file ()” auch ein mehrdimensionales Array hervorbringen kann, werde ich eine andere Lösung vorstellen. Zend_Config_Ini ()

 $conf = new Zend_COnfig_Ini("path/to/file.ini"); echo $conf -> one -> two -> three; // This is how easy it is to do so //prints one.two.three 

Ich bin mir ziemlich sicher, dass Sie dies versuchen, um einige Konfigurationsdaten oder ähnliches zu speichern.

Ich empfehle Ihnen, eine solche Datei als .ini zu speichern und die function parse_ini_file () zu verwenden, um die Konfigurationsdaten in ein mehrdimensionales Array zu ändern. So einfach ist das

 $confArray = parse_ini_file("filename.ini"); var_dump($confArray); 

Schnell und dreckig…

 < ?php $input = 'one.two.three = four'; list($key, $value) = explode('=', $input); foreach (explode('.', $key) as $keyName) { if (false === isset($source)) { $source = array(); $sourceRef = &$source; } $keyName = trim($keyName); $sourceRef = &$sourceRef[$keyName]; } $sourceRef = $value; unset($sourceRef); var_dump($source); 

Ich fand eine Lösung, die für mich funktionierte: Convert Flat PHP Array zu Nested Array basierend auf Array Keys und da ich ein Array auf Basis einer INI-Datei mit verschiedenen Schlüsseln hatte, machte ich eine kleine Modifikation dieses Skripts und machte mir Arbeit.

Mein Array sah so aus:

 [resources.db.adapter] => PDO_MYSQL [resources.db.params.host] => localhost [resources.db.params.dbname] => qwer [resources.db.params.username] => asdf ... 

Auf Anfrage ist dies der Code, den ich für mich geschrieben habe:

 < ?php echo "remove the exit :-)"; exit; $db_settings = parse_ini_file($_SERVER['DOCUMENT_ROOT'].'/website/var/config/app.ini'); echo "
"; print_r($db_settings); echo "

"; $resources = array(); foreach ($db_settings as $path => $value) { $ancestors = explode('.', $path); set_nested_value($resources, $ancestors, $value); } echo "

"; print_r($resources); echo "

"; /** * Give it and array, and an array of parents, it will decent into the * nested arrays and set the value. */ function set_nested_value(array &$arr, array $ancestors, $value) { $current = &$arr; foreach ($ancestors as $key) { // To handle the original input, if an item is not an array, // replace it with an array with the value as the first item. if (!is_array($current)) { $current = array( $current); } if (!array_key_exists($key, $current)) { $current[$key] = array(); } $current = &$current[$key]; } $current = $value; }

Dies ist die Quelle der INI-Datei, die von parse_ini_file () gelesen wird:

 Array ( [resources.db.adapter] => PDO_MYSQL [resources.db.params.host] => localhost [resources.db.params.dbname] => dbname [resources.db.params.username] => dbname_user [resources.db.params.password] => qwerqwerqwerqwer [resources.db.params.charset] => utf8 [externaldb.adapter] => PDO_MYSQL [externaldb.params.host] => localhost [externaldb.params.dbname] => dbname2 [externaldb.params.username] => dbname_user2 [externaldb.params.password] => qwerqwerwqerqerw [externaldb.params.charset] => latin1 ) 

Dies ist das Ergebnis des obigen Codes:

 Array ( [resources] => Array ( [db] => Array ( [adapter] => PDO_MYSQL [params] => Array ( [host] => localhost [dbname] => dbname [username] => dbname_user [password] => qwerqwerqwerqwer [charset] => utf8 ) ) ) [externaldb] => Array ( [adapter] => PDO_MYSQL [params] => Array ( [host] => localhost [dbname] => dbname2 [username] => dbname_user2 [password] => qwerqwerwqerqerw [charset] => latin1 ) ) )