query - separar cadenas de texto en php
Convierta la sintaxis de punto como "this.that.other" en una matriz multidimensional en PHP (7)
Aunque pasrse_ini_file () también puede traer una matriz multidimensional, presentaré una solución diferente. 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
Esta pregunta ya tiene una respuesta aquí:
Tal como lo implica el título, intento crear un analizador e intentar encontrar la solución óptima para convertir algo del espacio de nombres de punto en una matriz multidimensional de tal manera que
s1.t1.column.1 = size:33%
sería lo mismo que
$source[''s1''][''t1''][''column''][''1''] = ''size:33%'';
Encontré una solución que funcionó para mí en: Convert Flat PHP Array a Nested Array basado en Array Keys y como tenía una matriz basada en un archivo .ini con diferentes claves, realicé una pequeña modificación de esa secuencia de comandos y me funcionó.
Mi matriz se veía así:
[resources.db.adapter] => PDO_MYSQL
[resources.db.params.host] => localhost
[resources.db.params.dbname] => qwer
[resources.db.params.username] => asdf
...
A petición, este es el código que describí que estaba funcionando para mí:
<?php
echo "remove the exit :-)"; exit;
$db_settings = parse_ini_file($_SERVER[''DOCUMENT_ROOT''].''/website/var/config/app.ini'');
echo "<pre>";
print_r($db_settings);
echo "</pre>";
$resources = array();
foreach ($db_settings as $path => $value) {
$ancestors = explode(''.'', $path);
set_nested_value($resources, $ancestors, $value);
}
echo "<pre>";
print_r($resources);
echo "</pre>";
/**
* 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;
}
Esta es la fuente del archivo .ini leído por parse_ini_file ():
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
)
Este es el resultado del código anterior:
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
)
)
)
Estoy bastante seguro de que está intentando hacer esto para almacenar algunos datos de configuración o similares.
Le sugiero encarecidamente que guarde un archivo como .ini
y use la función parse_ini_file() para cambiar los datos de configuración en una matriz multidimensional. Tan simple como esto
$confArray = parse_ini_file("filename.ini");
var_dump($confArray);
FYI En Laravel tenemos una función auxiliar array_set()
que se traduce en esta función
Método para almacenar en una matriz usando notación de puntos
/**
* 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 simple como
$array = [''products'' => [''desk'' => [''price'' => 100]]];
array_set($array, ''products.desk.price'', 200);
// [''products'' => [''desk'' => [''price'' => 200]]]
Puede verificarlo en los documentos
Si necesita obtener los datos usando notación de puntos, el proceso es un poco más largo, pero se sirve en una placa mediante array_get()
que se traduce a esta función (en realidad, la fuente vinculada muestra toda la clase relacionada con la matriz auxiliar)
Método para leer desde una matriz usando notación de puntos
/**
* 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;
}
Como puede ver, utiliza dos submétodos, accessible()
e 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;
}
Y
/**
* 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);
}
Prueba este número ...
function assignArrayByPath(&$arr, $path, $value, $separator=''.'') {
$keys = explode($separator, $path);
foreach ($keys as $key) {
$arr = &$arr[$key];
}
$arr = $value;
}
Pasará por las teclas (delimitadas con .
De forma predeterminada) para llegar a la propiedad final y luego realizará la asignación en el valor.
Si algunas de las claves no están presentes, se crean.
Rápido y sucio...
<?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);
Sugeriría usar dflydev/dot-access-data .
Si no está familiarizado con el uso de Composer, diríjase a https://getcomposer.org/ para obtener una introducción, de modo que pueda descargar y cargar automáticamente el paquete como dependencia para su proyecto.
Una vez que tenga el paquete, puede cargar una matriz multidimensional en un objeto de Datos:
use Dflydev/DotAccessData/Data;
$data = new Data(array(
''s1'' => array(
''t1'' => array(
''column'' => array(
''1'' => ''size:33%'',
),
),
),
);
Y acceda a los valores usando la notación de puntos:
$size = $username = $data->get(''s1.t1.column.1'');