¿Guardar matriz PHP en MySQL?

88

¿Cuál es una buena manera de guardar una matriz de datos en un solo campo mysql?

Además, una vez que consulto esa matriz en la tabla mysql, ¿cuál es una buena manera de recuperarla en forma de matriz?

¿Serializar y no serializar es la respuesta?

JasonDavis
fuente

Respuestas:

87

No existe una buena forma de almacenar una matriz en un solo campo.

Debe examinar sus datos relacionales y realizar los cambios adecuados en su esquema. Consulte el ejemplo a continuación para obtener una referencia a este enfoque.

Si debe guardar la matriz en un solo campo, las funciones serialize()y unserialize()harán el truco. Pero no puede realizar consultas sobre el contenido real.

Como alternativa a la función de serialización, también existe json_encode()y json_decode().

Considere la siguiente matriz

$a = array(
    1 => array(
        'a' => 1,
        'b' => 2,
        'c' => 3
    ),
    2 => array(
        'a' => 1,
        'b' => 2,
        'c' => 3
    ),
);

Para guardarlo en la base de datos necesitas crear una tabla como esta

$c = mysql_connect($server, $username, $password);
mysql_select_db('test');
$r = mysql_query(
    'DROP TABLE IF EXISTS test');
$r = mysql_query(
    'CREATE TABLE test (
      id INTEGER UNSIGNED NOT NULL,
      a INTEGER UNSIGNED NOT NULL,
      b INTEGER UNSIGNED NOT NULL,
      c INTEGER UNSIGNED NOT NULL,
      PRIMARY KEY (id)
    )');

Para trabajar con los registros, puede realizar consultas como estas (y sí, este es un ejemplo, ¡cuidado!)

function getTest() {
    $ret = array();
    $c = connect();
    $query = 'SELECT * FROM test';
    $r = mysql_query($query,$c);
    while ($o = mysql_fetch_array($r,MYSQL_ASSOC)) {
        $ret[array_shift($o)] = $o;
    }
    mysql_close($c);
    return $ret;
}
function putTest($t) {
    $c = connect();
    foreach ($t as $k => $v) {
        $query = "INSERT INTO test (id,".
                implode(',',array_keys($v)).
                ") VALUES ($k,".
                implode(',',$v).
            ")";
        $r = mysql_query($query,$c);
    }
    mysql_close($c);
}

putTest($a);
$b = getTest();

La connect()función devuelve un recurso de conexión mysql

function connect() {
    $c = mysql_connect($server, $username, $password);
    mysql_select_db('test');
    return $c;
}
Peter Lindqvist
fuente
26

Generalmente, sí, serializar y anular serializar son el camino a seguir.

Sin embargo, si sus datos son algo simple, guardar como una cadena delimitada por comas probablemente sea mejor para el espacio de almacenamiento. Si sabe que su matriz será solo una lista de números, por ejemplo, entonces debería usar implosionar / explotar. Es la diferencia entre 1,2,3y a:3:{i:0;i:1;i:1;i:2;i:2;i:3;}.

De lo contrario, serialice y anule la serialización del trabajo para todos los casos.

Matchu
fuente
23
Ya que está aquí, lector, me voy a tomar el tiempo para anunciar que desde entonces he descubierto, a través de años de experiencia, que este no es realmente el camino a seguir. La respuesta aceptada es un enfoque mucho más sólido.
Matchu
4
Sine estás aquí, lector, voy a compartir contigo que simplemente depende de tus requisitos. Si no tiene necesidad de consultar los valores de su matriz y necesita algo que sea muy RÁPIDO, puede almacenar de manera segura sus datos como este en un solo campo (que es lo que indica claramente la pregunta), coloque una clave primaria en él y listo . Si se pregunta cuál es la aplicación: enviar datos a una cola que se cronometra cada 5 minutos. Otro cron crea las matrices, lo que lleva mucho más tiempo. La cola obtiene los datos calculados y los pasa a una API de terceros. No hay mejor forma de hacerlo.
Rid Iculous
1
@RidIculous Estoy confundido, ¿estás hablando de tu propia aplicación personal o de la aplicación que llevó a la pregunta?
Peter Lindqvist
1
Si bien eso es irrelevante para la premisa de mi declaración, el prefijo "Si se pregunta cuál es la aplicación" debería proporcionar claridad.
Rid Iculous
10

Simplemente use la función serializar PHP:

<?php
$myArray = array('1', '2');
$seralizedArray = serialize($myArray);
?>

Sin embargo, si está utilizando matrices simples como esa, también podría usar implosionar y explotar. Utilice una matriz en blanco en lugar de una nueva.

KramerC
fuente
9

Serializar / Deserializar arreglo para almacenamiento en una base de datos

Visite http://php.net/manual/en/function.serialize.php

Del manual de PHP:

Busque en "Volver" en la página

Devuelve una cadena que contiene una representación de flujo de bytes del valor que se puede almacenar en cualquier lugar.

Tenga en cuenta que esta es una cadena binaria que puede incluir bytes nulos y debe almacenarse y manejarse como tal. Por ejemplo, la salida serialize () generalmente debe almacenarse en un campo BLOB en una base de datos, en lugar de un campo CHAR o TEXT.

Nota: Si desea almacenar html en un blob, asegúrese de codificarlo en base64 o podría romper la función de serialización.

Codificación de ejemplo:

$YourSerializedData = base64_encode(serialize($theHTML));

$YourSerializedData ahora está listo para almacenarse en blob.

Después de obtener datos de blob, necesita base64_decode y luego anular la serialización de la decodificación de ejemplo:

$theHTML = unserialize(base64_decode($YourSerializedData));
lubina
fuente
8

La mejor manera que encontré es guardar la matriz como cadena de datos con caracteres separadores

$array = array("value1", "value2", "value3", "...", "valuen");
$array_data = implode("array_separator", $array);

$query = "INSERT INTO my_tbl_name (id, array_data) VALUES(NULL,'" . $array_data . "');";

Luego puede buscar datos, almacenados en su matriz con una simple consulta

$query = "SELECT * FROM my_tbl_name WHERE array_data LIKE '%value3%'";

use la función explode () para convertir la cadena "array_data" en una matriz

$array = explode("array_separator", $array_data);

tenga en cuenta que esto no funciona con matrices multidimensionales y asegúrese de que su "array_separator" sea único y no haya existido en los valores de matriz.

Ten cuidado !!! Si solo toma un formulario de datos y lo coloca en la base de datos, estará en una trampa, ¡porque los datos del formulario no son seguros para SQL! debe manejar el valor de su formulario con mysql_real_escape_string o si usa MySQLi mysqli :: real_escape_string o si el valor es entero o booleano (int) (boolean) en ellos

$number = (int)$_POST['number'];
$checked = (boolean) $_POST['checked'];

$name = mysql_real_escape_string($db_pt, $_POST['name']);
$email = mysqli_obj->real_escape_string($_POST['email']);
Harry
fuente
En mi caso, supongo que esta es la mejor opción para mí.
Imtiaz
6

Serializar y unserializar son bastante comunes para eso. También puede usar JSON a través de json_encode y json_decode para un formato menos específico de PHP.

ceejayoz
fuente
5

Como se mencionó anteriormente, si no necesita buscar datos dentro de la matriz, puede usar serializar, pero esto es "solo php". Por lo tanto, recomendaría usar json_decode / json_encode , no solo por rendimiento, sino también por legibilidad y portabilidad (otros lenguajes como javascript pueden manejar datos json_encoded).

Sebastián Lasse
fuente
3

Uhh, no sé por qué todos sugieren serializar la matriz.

Digo, la mejor manera es encajarlo en el esquema de su base de datos. No tengo idea (y no dio pistas) sobre el significado semántico real de los datos en su matriz, pero generalmente hay dos formas de almacenar secuencias como esa

create table mydata (
  id int not null auto_increment primary key,
  field1 int not null,
  field2 int not null,
  ...
  fieldN int not null
)

De esta manera, está almacenando su matriz en una sola fila.

create table mydata (
    id int not null auto_increment primary key,
    ...
)

create table myotherdata (
    id int not null auto_increment primary key,
    mydata_id int not null,
    sequence int not null,
    data int not null
)

La desventaja del primer método es, obviamente, que si tiene muchos elementos en su matriz, trabajar con esa tabla no será lo más elegante. También es poco práctico (posible, pero también bastante poco elegante, simplemente haga que las columnas sean anulables) trabajar con secuencias de longitud variable.

Para el segundo método, puede tener secuencias de cualquier longitud, pero de un solo tipo. Por supuesto, puede hacer que ese tipo varchar o algo así y serializar los elementos de su matriz. No es lo mejor que se puede hacer, pero ciertamente es mejor que serializar toda la matriz, ¿verdad?

De cualquier manera, cualquiera de estos métodos obtiene una clara ventaja de poder acceder a un elemento arbitrario de la secuencia y no tienes que preocuparte por serializar matrices y cosas feas como esas.

En cuanto a recuperarlo. Bueno, obtenga la fila / secuencia de filas apropiada con una consulta y, bueno, use un bucle ... ¿verdad?

shylent
fuente
A veces, una matriz es realmente apropiada. Si solo va a acceder a él como un atributo del primer objeto, entonces tiene sentido.
Matchu
1
Tengo que estar en desacuerdo en los términos más severos - me parece bastante inapropiado almacenar al azar, no estructurado (los "arreglos" php no son realmente arreglos en absoluto, ¿verdad?), Blobs de datos sin tipo en una base de datos relacional . ¿Qué vas a usar para un separador de todos modos, si tu matriz puede tener cadenas? Esto solo busca problemas de muchas maneras diferentes. En el 99,9% de los casos, existe otra forma más natural. Haré una suposición alocada aquí y sugeriré que el caso del interrogador no cae en el 0.1% restante.
shylent
2
De hecho, a veces es muy apropiado almacenar una matriz en un campo en una base de datos. Un ejemplo serían los metadatos como una tabla de 'variables' globales en la que los complementos y módulos de un sistema pueden almacenar sus configuraciones variadas. una tabla que almacena datos de 'sesión' arbitrarios podría implementarse mejor utilizando un campo que contenga una matriz asociativa de claves / valores. serialize y unserialize (que es la respuesta correcta) se encarga de los separadores. verifique algunos de los varios proyectos de código abierto exitosos y populares, como WordPress o Drupal, y verá que las matrices a veces se almacenan en la base de datos de esta manera
Scott Evernden
@Scott Evernden: Supongo que tienes razón después de todo. php no es mi lenguaje "principal", por lo que estaba juzgando la solución desde la perspectiva del diseño de la base de datos. Si lo que describe es realmente la forma común de hacer tales cosas (en php), que así sea. Aunque no me gusta :)
shylent
5
NUNCA es apropiado almacenar una matriz en un campo en una base de datos. Es una violación no de cuarta forma normal, tercera forma normal o incluso segunda forma normal: es una VIOLACIÓN DE PRIMERA FORMA NORMAL. Si no puede adherirse ni siquiera a la primera forma normal, hay un problema grave en su aplicación. Eso se aplica a Drupal y Wordpress; si hacen esto ciertamente no es porque esa faceta de sus aplicaciones esté bien diseñada. Tuve este argumento en mi último trabajo, y debido a que XCart estaba haciendo estas tonterías, hizo algo que debería haber sido posible, extremadamente difícil en su lugar.
Dexygen
2

Puede guardar su matriz como json.
hay documentación para el tipo de datos json: https://dev.mysql.com/doc/refman/5.7/en/json.html
Creo que esta es la mejor solución y lo ayudará a mantener su código más legible al evitar funciones locas .
Espero que esto sea útil para ti.

Roberto Murguía
fuente
0

Sí, serializar / unserializar es lo que más he visto en muchos proyectos de código abierto.

Eduardo
fuente
0

Sugeriría usar implosionar / explotar con un carácter que sepa que no estará contenido en ninguno de los elementos individuales de la matriz. Luego guárdelo en SQL como una cadena.

usuario1478500
fuente
3
Esta pregunta se hizo hace 3 años y tiene una respuesta aceptada. Puede que le resulte más útil responder preguntas más nuevas o preguntas sin respuesta.
MDrollette
0

compruebe la función de implosión, ya que los valores están en una matriz, desea poner los valores de la matriz en una consulta mysql que inserta los valores en una tabla.

$query = "INSERT INto hardware (specifications) VALUES (".implode(",",$specifications).")";

Si los valores de la matriz son valores de texto, deberá agregar comillas

$query = "INSERT INto hardware (specifications) VALUES ("'.implode("','",$specifications)."')";

mysql_query($query);

Además, si no desea valores duplicados, cambie "INto" a "IGNORE" y solo se insertarán valores únicos en la tabla.

j0k
fuente
Si tiene una clave principal, no obtendrá duplicados con INSERT INTO de todos modos. Si no tiene una clave principal o un índice, IGNORE no hace ninguna diferencia.
Peter Lindqvist
0

puede insertar un objeto serializado (matriz) en mysql, ejemplo serialize($object)y puede unserizar un objeto ejemplounserialize($object)

Vildan Bina
fuente
-5

En lugar de guardarlo en la base de datos, guárdelo en un archivo y luego llámelo más tarde.

Lo que hacen muchas aplicaciones php (como sugarcrm) es simplemente usar var_export para hacer eco de todos los datos de la matriz en un archivo. Esto es lo que uso para guardar mis datos de configuración:

private function saveConfig() {
    file_put_contents($this->_data['pathtocompileddata'],'<?php' . PHP_EOL . '$acs_confdata = ' . var_export($this->_data,true) . ';');        
}

¡Creo que esta es una mejor manera de guardar sus datos!

AntonioCS
fuente
Es otra forma, no necesariamente mejor.
Peter Lindqvist
En efecto. Simplemente creo que acceder al archivo es mucho más fácil que consultar la base de datos para recuperar los datos de la matriz y luego inicializar la matriz. De esta manera, solo incluye el archivo y listo.
AntonioCS