variable var_export var_dump values tipo que print imprimir consola array php var-dump

php - var_export - Convierte var_dump de array a variable de matriz



printf array php (7)

Creo que estás buscando la función serialize :

serialize - Genera una representación almacenable de un valor

Le permite guardar los contenidos de la matriz en formato legible y luego puede leer la matriz con la función de unserialize .

Usando estas funciones, puede almacenar / recuperar las matrices incluso en archivos de texto / planos así como en la base de datos.

Nunca había pensado en esto hasta hoy, pero después de buscar en la web no encontré nada. Tal vez no estaba redactando bien en la búsqueda.

Dada una matriz (de dimensiones múltiples o no):

$data = array(''this'' => array(''is'' => ''the''), ''challenge'' => array(''for'' => array(''you'')));

Cuando var_dumped:

array(2) { ["this"]=> array(1) { ["is"]=> string(3) "the" } ["challenge"]=> array(1) { ["for"]=> array(1) { [0]=> string(3) "you" } } }

El desafío es este: ¿Cuál es el mejor método optimizado para recompilar la matriz a una matriz utilizable para PHP? Como una función undump_var() . Si los datos están todos en una línea como salida en un navegador o si contienen los saltos de línea como salida a la terminal.

¿Es solo una cuestión de expresiones regulares? ¿O hay alguna otra manera? Estoy buscando creatividad.

ACTUALIZACIÓN: Nota. Estoy familiarizado con serializar y deserializar gente. No estoy buscando soluciones alternativas. Este es un desafío de código para ver si se puede hacer de una manera optimizada y creativa. Así que serializar y var_export no son soluciones aquí. Tampoco son las mejores respuestas.


El truco es hacer coincidir los trozos de código y "strings" , y en cadenas no hacer nada más que hacer los reemplazos:

$out = preg_replace_callback(''/"[^"]*"|[^"]+/'',''repl'',$in); function repl($m) { return $m[0][0]==''"''? str_replace(''"'',"''",$m[0]) : str_replace("(,","(", preg_replace("/(int/((/d+)/)|/s*|(string|)/(/d+/))/","//2", strtr($m[0],"{}[]","(), ") ) ); }

productos:

array(''this''=>array(''is''=>''the''),''challenge''=>array(''for''=>array(0=>''you'')))

(eliminar las teclas numéricas ascendentes comenzando en 0 requiere un poco de contabilidad adicional, lo que se puede hacer en la función repl ).

PD. esto no resuelve el problema de las cadenas que contienen " , pero como parece que var_dump no escapa al contenido de la cadena, no hay forma de resolverlo de manera confiable. (Podría hacer coincidir /["[^"]*"/] pero una cadena también puede contener "]


No hay otra manera que el análisis manual según el tipo. No agregué soporte para objetos, pero es muy similar al de matrices; solo necesita hacer algo de magia de reflexión para poblar no solo las propiedades públicas y no activar el constructor.

EDITAR: Añadido soporte para objetos ... Reflection magic ...

function unserializeDump($str, &$i = 0) { $strtok = substr($str, $i); switch ($type = strtok($strtok, "(")) { // get type, before first parenthesis case "bool": return strtok(")") === "true"?(bool) $i += 10:!$i += 11; case "int": $int = (int)substr($str, $i + 4); $i += strlen($int) + 5; return $int; case "string": $i += 11 + ($len = (int)substr($str, $i + 7)) + strlen($len); return substr($str, $i - $len - 1, $len); case "float": return (float)($float = strtok(")")) + !$i += strlen($float) + 7; case "NULL": return NULL; case "array": $array = array(); $len = (int)substr($str, $i + 6); $i = strpos($str, "/n", $i) - 1; for ($entries = 0; $entries < $len; $entries++) { $i = strpos($str, "/n", $i); $indent = -1 - (int)$i + $i = strpos($str, "[", $i); // get key int/string if ($str[$i + 1] == ''"'') { // use longest possible sequence to avoid key and dump structure collisions $key = substr($str, $i + 2, - 2 - $i + $i = strpos($str, "/"]=>/n ", $i)); } else { $key = (int)substr($str, $i + 1); $i += strlen($key); } $i += $indent + 5; // jump line $array[$key] = unserializeDump($str, $i); } $i = strpos($str, "}", $i) + 1; return $array; case "object": $reflection = new ReflectionClass(strtok(")")); $object = $reflection->newInstanceWithoutConstructor(); $len = !strtok("(") + strtok(")"); $i = strpos($str, "/n", $i) - 1; for ($entries = 0; $entries < $len; $entries++) { $i = strpos($str, "/n", $i); $indent = -1 - (int)$i + $i = strpos($str, "[", $i); // use longest possible sequence to avoid key and dump structure collisions $key = substr($str, $i + 2, - 2 - $i + $i = min(strpos($str, "/"]=>/n ", $i)?:INF, strpos($str, "/":protected]=>/n ", $i)?:INF, $priv = strpos($str, "/":/"", $i)?:INF)); if ($priv == $i) { $ref = new ReflectionClass(substr($str, $i + 3, - 3 - $i + $i = strpos($str, "/":private]=>/n ", $i))); $i += $indent + 13; // jump line } else { $i += $indent + ($str[$i+1] == ":"?15:5); // jump line $ref = $reflection; } $prop = $ref->getProperty($key); $prop->setAccessible(true); $prop->setValue($object, unserializeDump($str, $i)); } $i = strpos($str, "}", $i) + 1; return $object; } throw new Exception("Type not recognized...: $type"); }

(Aquí hay una gran cantidad de números "mágicos" cuando se incrementa el contador de posición de cadena $i , principalmente solo las longitudes de cadena de las palabras clave y algunos paréntesis, etc.)


Se actualizó para NO USAR create_function, ya que está DEPRECADO a partir de PHP 7.2.0. En su lugar, se reemplaza para usar funciones anónimas:

function unvar_dump($str) { if (strpos($str, "/n") === false) { //Add new lines: $regex = array( ''#(/[.*?/]=>)#'', ''#(string/(|int/(|float/(|array/(|NULL|object/(|})#'', ); $str = preg_replace($regex, "/n/1", $str); $str = trim($str); } $regex = array( ''#^/040*NULL/040*$#m'', ''#^/s*array/((.*?)/)/s*{/s*$#m'', ''#^/s*string/((.*?)/)/s*(.*?)$#m'', ''#^/s*int/((.*?)/)/s*$#m'', ''#^/s*bool/(true/)/s*$#m'', ''#^/s*bool/(false/)/s*$#m'', ''#^/s*float/((.*?)/)/s*$#m'', ''#^/s*/[(/d+)/]/s*=>/s*$#m'', ''#/s*?/r?/n/s*#m'', ); $replace = array( ''N'', ''a:/1:{'', ''s:/1:/2'', ''i:/1'', ''b:1'', ''b:0'', ''d:/1'', ''i:/1'', '';'' ); $serialized = preg_replace($regex, $replace, $str); $func = function($match) { return ''s:''.strlen($match[1]).'':"''.$match[1].''"''; }; $serialized = preg_replace_callback( ''#/s*/["(.*?)"/]/s*=>#'', $func, $serialized ); $func = function($match) { return ''O:''.strlen($match[1]).'':"''.$match[1].''":''.$match[2].'':{''; }; $serialized = preg_replace_callback( ''#object/((.*?)/).*?/((/d+)/)/s*{/s*;#'', $func, $serialized ); $serialized = preg_replace( array(''#};#'', ''#{;#''), array(''}'', ''{''), $serialized ); return unserialize($serialized); } $test = ''array(10) { ["status"]=> string(1) "1" ["transactionID"]=> string(14) "1532xxx" ["orderID"]=> string(10) "1532xxx" ["value"]=> string(8) "0.73xxx" ["address"]=> string(1) "-" ["confirmations"]=> string(3) "999" ["transaction_hash"]=> string(64) "internxxx" ["notes"]=> string(0) "" ["txCost"]=> string(1) "0" ["txTimestamp"]=> string(10) "1532078165" }''; var_export(unvar_dump($test));


Si desea codificar / decodificar una matriz como esta, debe usar var_export() , que genera resultados en la matriz de PHP para, por ejemplo:

array( 1 => ''foo'', 2 => ''bar'' )

podría ser el resultado de eso. Sin embargo, debería usar eval() para recuperar la matriz, y esa es una forma potencialmente peligrosa (especialmente porque eval() realmente ejecuta código PHP, por lo que una simple inyección de código podría hacer que los hackers puedan controlar su script PHP )

Algunas soluciones aún mejores son serialize() , que crea una versión serializada de cualquier matriz u objeto; y json_encode() , que codifica cualquier matriz u objeto con el formato JSON (que es más preferido para el intercambio de datos entre diferentes idiomas).


Use regexp para cambiar array (.) {(. *)} A array ($ 1) y evalúe el código, esto no es tan fácil como está escrito porque tiene que lidiar con paréntesis coincidentes, etc., solo una pista sobre cómo encontrar una solución ;)

  • esto será útil si no puedes cambiar var_dump a var_export, o serializar

var_export o serialize es lo que estás buscando. var_export renderizará una sintaxis de matriz analizable PHP, y serialize generará una conversión de "matriz a cadena" no legible, pero no humanamente legible ...

Editar bien, para el desafío:

Básicamente, convierto la salida en una cadena serializada (y luego la deserializo). No pretendo que esto sea perfecto, pero parece funcionar en algunas estructuras bastante complejas que he intentado ...

function unvar_dump($str) { if (strpos($str, "/n") === false) { //Add new lines: $regex = array( ''#(//[.*?//]=>)#'', ''#(string//(|int//(|float//(|array//(|NULL|object//(|})#'', ); $str = preg_replace($regex, "/n//1", $str); $str = trim($str); } $regex = array( ''#^//040*NULL//040*$#m'', ''#^//s*array//((.*?)//)//s*{//s*$#m'', ''#^//s*string//((.*?)//)//s*(.*?)$#m'', ''#^//s*int//((.*?)//)//s*$#m'', ''#^//s*bool//(true//)//s*$#m'', ''#^//s*bool//(false//)//s*$#m'', ''#^//s*float//((.*?)//)//s*$#m'', ''#^//s*/[(//d+)//]//s*=>//s*$#m'', ''#//s*?//r?//n//s*#m'', ); $replace = array( ''N'', ''a://1:{'', ''s://1://2'', ''i://1'', ''b:1'', ''b:0'', ''d://1'', ''i://1'', '';'' ); $serialized = preg_replace($regex, $replace, $str); $func = create_function( ''$match'', ''return "s:".strlen($match[1])."://"".$match[1]."//"";'' ); $serialized = preg_replace_callback( ''#//s*//["(.*?)"//]//s*=>#'', $func, $serialized ); $func = create_function( ''$match'', ''return "O:".strlen($match[1])."://"".$match[1]."//":".$match[2].":{";'' ); $serialized = preg_replace_callback( ''#object//((.*?)//).*?//((//d+)//)//s*{//s*;#'', $func, $serialized ); $serialized = preg_replace( array(''#};#'', ''#{;#''), array(''}'', ''{''), $serialized ); return unserialize($serialized); }

Lo probé en una estructura compleja como:

array(4) { ["foo"]=> string(8) "Foo"bar"" [0]=> int(4) [5]=> float(43.2) ["af"]=> array(3) { [0]=> string(3) "123" [1]=> object(stdClass)#2 (2) { ["bar"]=> string(4) "bart" ["foo"]=> array(1) { [0]=> string(2) "re" } } [2]=> NULL } }