Salvare l'array PHP su MySQL?


88

Qual è un buon modo per salvare un array di dati in un singolo campo mysql?

Inoltre, una volta che ho interrogato quell'array nella tabella mysql, qual è un buon modo per riportarlo in forma di array?

Serializzare e deserializzare la risposta?

Risposte:


87

Non esiste un modo valido per memorizzare un array in un singolo campo.

È necessario esaminare i dati relazionali e apportare le modifiche appropriate allo schema. Vedere l'esempio di seguito per un riferimento a questo approccio.

Se è necessario salvare l'array in un singolo campo, le funzioni serialize()e unserialize()faranno il trucco. Ma non puoi eseguire query sul contenuto effettivo.

In alternativa alla funzione di serializzazione c'è anche json_encode()e json_decode().

Considera il seguente array

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

Per salvarlo nel database è necessario creare una tabella come questa

$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)
    )');

Per lavorare con i record puoi eseguire query come queste (e sì, questo è un esempio, attenzione!)

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()funzione restituisce una risorsa di connessione mysql

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

26

In generale, sì, serializzare e deserializzare sono la strada da percorrere.

Se i tuoi dati sono qualcosa di semplice, però, il salvataggio come una stringa delimitata da virgole sarebbe probabilmente meglio per lo spazio di archiviazione. Se sai che il tuo array sarà solo un elenco di numeri, per esempio, allora dovresti usare implode / explode. È la differenza tra 1,2,3e a:3:{i:0;i:1;i:1;i:2;i:2;i:3;}.

In caso contrario, serializzare e deserializzare il lavoro per tutti i casi.


23
Dato che sei qui, lettore, mi prenderò il tempo per annunciare che da allora ho scoperto, attraverso anni di esperienza, che questa non è davvero la strada da percorrere. La risposta accettata è un approccio molto più forte.
Matchu

4
Dato che sei qui, lettore, condividerò con te che dipende semplicemente dalle tue esigenze. Se non hai bisogno di eseguire query in base ai valori dell'array e hai bisogno di qualcosa che sia molto VELOCE, puoi archiviare in sicurezza i tuoi dati in questo modo in un singolo campo (che è ciò che la domanda ha chiaramente indicato), schiaffo una chiave primaria su di esso e il gioco è fatto . Se ti chiedi quale sia l'applicazione: inserire i dati in una coda che viene cronizzata ogni 5 minuti. Un altro cron crea gli array che richiedono molto più tempo. La coda recupera i dati calcolati e li passa a un'API di terze parti. Non c'è modo migliore per farlo.
Rid Iculous

1
@RidIculous Sono confuso, stai parlando della tua applicazione personale o dell'applicazione che ha portato alla domanda?
Peter Lindqvist

1
Sebbene ciò sia irrilevante per la premessa della mia affermazione, il prefisso "Se ti chiedi qual è la domanda" dovrebbe fornire chiarezza.
Rid Iculous

10

Usa semplicemente la funzione serializza PHP:

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

Tuttavia, se stai usando array semplici come quello potresti anche usare implode ed explode.Usa un array vuoto invece di nuovo.


9

Serializza / Annulla la serializzazione dell'array per l'archiviazione in un database

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

Dal manuale PHP:

Guarda sotto "Reso" nella pagina

Restituisce una stringa contenente una rappresentazione del flusso di byte del valore che può essere archiviata ovunque.

Si noti che questa è una stringa binaria che può includere byte nulli e deve essere archiviata e gestita come tale. Ad esempio, l'output di serialize () dovrebbe generalmente essere memorizzato in un campo BLOB in un database, piuttosto che in un campo CHAR o TEXT.

Nota: se si desidera archiviare html in un BLOB, assicurarsi di codificarlo in base64 o potrebbe interrompere la funzione di serializzazione.

Codifica di esempio:

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

$YourSerializedData è ora pronto per essere archiviato in BLOB.

Dopo aver ottenuto i dati dal blob, è necessario base64_decode quindi deserializzare la decodifica dell'esempio:

$theHTML = unserialize(base64_decode($YourSerializedData));

8

Il modo migliore, che ho scoperto a me stesso, è salvare l'array come stringa di dati con caratteri separatori

$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 . "');";

È quindi possibile cercare i dati, archiviati nel proprio array con una semplice query

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

usa la funzione explode () per convertire la stringa "array_data" in array

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

nota che questo non funziona con gli array multidimensionali e assicurati che il tuo "array_separator" sia unico e non esistesse nei valori degli array.

Stai attento !!! se prendi solo i dati di un modulo e lo metti nel database, sarai in trappola, perché i dati del modulo non sono sicuri per SQL! devi gestire il valore del tuo modulo con mysql_real_escape_string o se usi MySQLi mysqli :: real_escape_string o se il valore è intero o booleano cast (int) (booleano) su di essi

$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']);

Nel mio caso, credo che questa sia l'opzione migliore per me.
Imtiaz

6

Serializzare e deserializzare sono piuttosto comuni per questo. Puoi anche usare JSON tramite json_encode e json_decode per un formato meno specifico di PHP.


5

Come accennato prima - Se non hai bisogno di cercare dati all'interno dell'array, puoi usare serialize - ma questo è "solo php". Quindi consiglierei di usare json_decode / json_encode - non solo per le prestazioni ma anche per la leggibilità e la portabilità (altri linguaggi come javascript possono gestire i dati json_encoded).


3

Uhh, non so perché tutti suggeriscano di serializzare l'array.

Dico, il modo migliore è adattarlo effettivamente allo schema del database. Non ho idea (e non hai fornito indizi) sull'effettivo significato semantico dei dati nel tuo array, ma ci sono generalmente due modi per memorizzare sequenze del genere

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

In questo modo stai memorizzando il tuo array in una singola riga.

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
)

Lo svantaggio del primo metodo è, ovviamente, che se hai molti elementi nel tuo array, lavorare con quella tabella non sarà la cosa più elegante. È anche poco pratico (possibile, ma anche abbastanza inelegante - basta rendere le colonne annullabili) lavorare con sequenze di lunghezza variabile.

Per il secondo metodo, puoi avere sequenze di qualsiasi lunghezza, ma di un solo tipo. Ovviamente puoi fare in modo che un tipo varchar o qualcosa del genere e serializzare gli elementi del tuo array. Non è la cosa migliore da fare, ma sicuramente meglio che serializzare l'intero array, giusto?

Ad ogni modo, uno qualsiasi di questi metodi ottiene un chiaro vantaggio di essere in grado di accedere a un elemento arbitrario della sequenza e non devi preoccuparti di serializzare array e cose brutte del genere.

Quanto a riaverlo indietro. Bene, ottieni la riga / sequenza di righe appropriata con una query e, beh, usa un ciclo .. giusto?


A volte un array è davvero appropriato. Se hai intenzione di accedervi solo come attributo del primo oggetto, allora ha senso.
Matchu

1
Devo essere in disaccordo nei termini più severi: mi sembra piuttosto inappropriato memorizzare casuali, non strutturati (gli "array" php non sono affatto array, giusto?), Blob di dati non tipizzati in un database relazionale . Cosa userete comunque per un separatore, se il vostro array potrebbe contenere stringhe? Questo è solo chiedere guai in molti modi diversi. Nel 99,9% dei casi c'è un altro modo più naturale. Farò un'ipotesi selvaggia qui e suggerisco che il caso dell'interrogante non rientra nel restante 0,1%.
shylent

2
In realtà, a volte è molto appropriato memorizzare un array in un campo in un DB. Un esempio potrebbero essere i metadati come una tabella di "variabili" globali in cui i plug-in e i moduli di un sistema possono memorizzare le loro impostazioni assortite. una tabella che memorizza dati arbitrari di "sessione" potrebbe essere implementata al meglio utilizzando un campo che contiene un array associativo di chiavi / valori. serialize e unserialize (che è la risposta corretta) si prendono cura dei separatori. controlla alcuni dei numerosi progetti open source di successo e popolari, come WordPress o Drupal - e vedrai che gli array a volte sono memorizzati nel DB in questo modo
Scott Evernden

@ Scott Evernden: immagino che tu abbia ragione, dopotutto. php non è il mio linguaggio "principale", quindi stavo giudicando la soluzione dal punto di vista della progettazione del database. Se quello che descrivi è davvero il modo comune di fare queste cose (in php), allora così sia. Non mi piace però :)
shylent

5
Non è MAI appropriato memorizzare un array in un campo in un DB. È una violazione non della quarta forma normale, della terza forma normale o anche della seconda forma normale: è una VIOLAZIONE DELLA PRIMA FORMA NORMALE. Se non puoi aderire nemmeno al primo modulo normale, c'è qualcosa di gravemente sbagliato nella tua domanda. Questo vale per Drupal e Wordpress; se lo fanno non è certamente perché quell'aspetto delle loro app sono ben progettate .. Ho avuto questo argomento nel mio ultimo lavoro, e poiché XCart stava facendo queste sciocchezze, ha reso qualcosa che avrebbe dovuto essere possibile, estremamente difficile invece.
Dexygen


0

Sì, serializzare / deserializzare è ciò che ho visto di più in molti progetti open source.


0

Suggerirei di usare implodere / esplodere con un carattere che sai non sarà contenuto in nessuno dei singoli elementi dell'array. Quindi memorizzalo in SQL come stringa.


3
Questa domanda è stata posta 3 anni fa e ha una risposta accettata. Potresti trovare più utile rispondere a nuove domande o domande senza risposta.
MDrollette

0

controlla la funzione implode, poiché i valori sono in un array, vuoi mettere i valori dell'array in una query mysql che inserisce i valori in una tabella.

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

Se i valori nella matrice sono valori di testo, sarà necessario aggiungere virgolette

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

mysql_query($query);

Inoltre, se non desideri valori duplicati, imposta "INto" su "IGNORE" e nella tabella verranno inseriti solo valori univoci.


Se hai una chiave primaria, non ottieni comunque duplicati con INSERT INTO. Se non hai una chiave primaria o un indice IGNORE non fa alcuna differenza.
Peter Lindqvist

0

puoi inserire un oggetto serializzato (array) in mysql, esempio serialize($object)e puoi annullare la classificazione dell'oggetto exampleunserialize($object)


-5

Invece di salvarlo nel database, salvarlo in un file e richiamarlo in seguito.

Quello che fanno molte app php (come sugarcrm) è usare semplicemente var_export per riprodurre tutti i dati dell'array in un file. Questo è ciò che utilizzo per salvare i dati delle mie configurazioni:

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

Penso che questo sia un modo migliore per salvare i tuoi dati!


È un altro modo, non necessariamente migliore.
Peter Lindqvist il

Infatti. Penso solo che l'accesso al file sia molto più semplice che interrogare il database per recuperare i dati dell'array e quindi inizializzare l'array. In questo modo includi semplicemente il file e il gioco è fatto.
AntonioCS
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.