PHP-Array in MySQL speichern?

87

Was ist ein guter Weg, um ein Datenarray in einem einzelnen MySQL-Feld zu speichern?

Was ist ein guter Weg, um dieses Array wieder in die Array-Form zu bringen, wenn ich es in der MySQL-Tabelle abgefragt habe?

Ist serialisieren und unserialisieren die Antwort?

JasonDavis
quelle

Antworten:

86

Es gibt nichts Gutes Möglichkeit, ein Array in einem einzelnen Feld zu speichern.

Sie müssen Ihre relationalen Daten untersuchen und die entsprechenden Änderungen an Ihrem Schema vornehmen. Im folgenden Beispiel finden Sie einen Verweis auf diesen Ansatz.

Wenn Sie das Array in einem einzelnen Feld speichern müssen , dann das serialize()undunserialize() reichen die Funktionen . Sie können jedoch keine Abfragen zum tatsächlichen Inhalt durchführen.

Alternativ zur Serialisierungsfunktion gibt es auch json_encode()und json_decode().

Betrachten Sie das folgende Array

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

Um es in der Datenbank zu speichern, müssen Sie eine solche Tabelle erstellen

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

Um mit den Datensätzen zu arbeiten, können Sie Abfragen wie diese ausführen (und ja, dies ist ein Beispiel, Vorsicht!).

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();

Die connect()Funktion gibt eine MySQL-Verbindungsressource zurück

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

Im Allgemeinen sind Serialisierung und Unserialisierung der richtige Weg.

Wenn Ihre Daten jedoch einfach sind, ist das Speichern als durch Kommas getrennte Zeichenfolge wahrscheinlich besser für den Speicherplatz. Wenn Sie wissen, dass Ihr Array beispielsweise nur eine Liste von Zahlen ist, sollten Sie implode / explode verwenden. Es ist der Unterschied zwischen 1,2,3und a:3:{i:0;i:1;i:1;i:2;i:2;i:3;}.

Wenn nicht, serialisieren und unserialisieren Sie die Arbeit für alle Fälle.

Matchu
quelle
22
Da Sie hier sind, Leser, werde ich mir nur die Zeit nehmen, um bekannt zu geben, dass ich durch jahrelange Erfahrung herausgefunden habe, dass dies wirklich nicht der richtige Weg ist. Die akzeptierte Antwort ist ein viel stärkerer Ansatz.
Matchu
4
Da Sie hier sind, Leser, werde ich Ihnen mitteilen, dass es einfach von Ihren Anforderungen abhängt. Wenn Sie nicht nach Ihren Array-Werten abfragen müssen und etwas benötigen, das sehr SCHNELL ist, können Sie Ihre Daten sicher in einem einzigen Feld speichern (wie in der Frage klar angegeben), einen Primärschlüssel darauf legen und los geht's . Wenn Sie sich fragen, was die Anwendung ist: Daten in eine Warteschlange verschieben, die alle 5 Minuten erstellt wird. Ein anderer Cron erstellt die Arrays, was viel mehr Zeit in Anspruch nimmt. Die Warteschlange ruft die berechneten Daten ab und übergibt sie an eine API eines Drittanbieters. Es gibt keinen besseren Weg, es zu tun.
Rid Iculous
1
@RidIculous Ich bin verwirrt, sprechen Sie über Ihre persönliche Bewerbung oder die Bewerbung, die dazu geführt hat, dass die Frage gestellt wurde?
Peter Lindqvist
1
Während dies für die Prämisse meiner Aussage irrelevant ist, sollte das Präfix "Wenn Sie sich fragen, was die Anwendung ist" Klarheit schaffen.
Rid Iculous
10

Verwenden Sie einfach die Funktion zum Serialisieren von PHP:

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

Wenn Sie jedoch einfache Arrays wie dieses verwenden, können Sie auch implodieren und explodieren verwenden. Verwenden Sie ein leeres Array anstelle eines neuen.

KramerC
quelle
9

Serialize / Unserialize-Array zur Speicherung in einer DB

Besuchen Sie http://php.net/manual/en/function.serialize.php

Aus dem PHP-Handbuch:

Schauen Sie auf der Seite unter "Zurück" nach

Gibt eine Zeichenfolge zurück, die eine Byte-Stream-Darstellung des Werts enthält, der überall gespeichert werden kann.

Beachten Sie, dass dies eine binäre Zeichenfolge ist, die Null-Bytes enthalten kann und als solche gespeichert und behandelt werden muss. Beispielsweise sollte die Ausgabe von serialize () im Allgemeinen in einem BLOB-Feld in einer Datenbank und nicht in einem CHAR- oder TEXT-Feld gespeichert werden.

Hinweis: Wenn Sie HTML in einem Blob speichern möchten, müssen Sie es unbedingt mit base64 codieren, da sonst die Serialisierungsfunktion unterbrochen werden kann.

Beispielcodierung:

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

$YourSerializedData ist jetzt bereit, im Blob gespeichert zu werden.

Nachdem Sie Daten vom Blob erhalten haben, müssen Sie base64_decode und dann unserialisieren. Beispieldecodierung:

$theHTML = unserialize(base64_decode($YourSerializedData));
Seebarsch
quelle
8

Der beste Weg, den ich für mich gefunden habe, ist das Speichern eines Arrays als Datenzeichenfolge mit Trennzeichen

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

Sie können dann mit einfacher Abfrage nach Daten suchen, die in Ihrem Array gespeichert sind

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

Verwenden Sie die Funktion explode (), um die Zeichenfolge "array_data" in ein Array zu konvertieren

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

Beachten Sie, dass dies nicht mit mehrdimensionalen Arrays funktioniert, und stellen Sie sicher, dass Ihr "array_separator" eindeutig ist und in Array-Werten nicht vorhanden war.

Achtung !!! Wenn Sie nur Formulardaten nehmen und in die Datenbank stellen, befinden Sie sich in einer Falle, da die Formulardaten nicht SQL-sicher sind! Sie müssen Ihren Formularwert mit mysql_real_escape_string behandeln oder wenn Sie MySQLi mysqli :: real_escape_string verwenden oder wenn der Wert eine Ganzzahl oder eine boolesche Umwandlung (int) (boolean) ist

$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
quelle
In meinem Fall denke ich, dass dies die beste Option für mich ist.
Imtiaz
6

Serialisieren und unserialisieren sind dafür ziemlich üblich. Sie können JSON auch über json_encode und json_decode für ein weniger PHP-spezifisches Format verwenden.

ceejayoz
quelle
5

Wie bereits erwähnt - Wenn Sie nicht nach Daten innerhalb des Arrays suchen müssen, können Sie serialize verwenden - dies ist jedoch "nur PHP". Daher würde ich empfehlen, json_decode / json_encode zu verwenden - nicht nur für die Leistung, sondern auch für die Lesbarkeit und Portabilität (andere Sprachen wie Javascript können mit json_encodierten Daten umgehen).

Sebastian Lasse
quelle
3

Ich weiß nicht, warum jeder vorschlägt, das Array zu serialisieren.

Ich sage, der beste Weg ist, es tatsächlich in Ihr Datenbankschema zu integrieren. Ich habe keine Ahnung (und Sie haben keine Hinweise gegeben) über die tatsächliche semantische Bedeutung der Daten in Ihrem Array, aber es gibt im Allgemeinen zwei Möglichkeiten, solche Sequenzen zu speichern

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

Auf diese Weise speichern Sie Ihr Array in einer einzelnen Zeile.

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
)

Der Nachteil der ersten Methode besteht natürlich darin, dass die Arbeit mit dieser Tabelle nicht die eleganteste Sache ist, wenn Sie viele Elemente in Ihrem Array haben. Es ist auch unpraktisch (möglich, aber auch ziemlich unelegant - machen Sie die Spalten einfach nullbar), mit Sequenzen variabler Länge zu arbeiten.

Bei der zweiten Methode können Sie Sequenzen beliebiger Länge, jedoch nur eines Typs verwenden. Sie können natürlich diesen einen Typ varchar oder so machen und die Elemente Ihres Arrays serialisieren. Nicht das Beste, aber sicherlich besser, als das gesamte Array zu serialisieren, oder?

In beiden Fällen hat jede dieser Methoden den klaren Vorteil, auf ein beliebiges Element der Sequenz zugreifen zu können, und Sie müssen sich nicht um die Serialisierung von Arrays und solche hässlichen Dinge kümmern.

Wie für die Rückgabe. Holen Sie sich die entsprechende Zeile / Folge von Zeilen mit einer Abfrage und verwenden Sie eine Schleife . Richtig?

shylent
quelle
Manchmal ist ein Array wirklich angemessen. Wenn Sie nur als Attribut des ersten Objekts darauf zugreifen, ist dies sinnvoll.
Matchu
1
Ich muss in den strengsten Begriffen nicht zustimmen - es scheint mir ziemlich unangemessen, zufällige, unstrukturierte (PHP- "Arrays" sind eigentlich gar keine Arrays, oder?), Nicht typisierte Datenblobs in einer relationalen Datenbank zu speichern . Was werden Sie überhaupt für ein Trennzeichen verwenden, wenn Ihr Array möglicherweise Zeichenfolgen enthält? Dies verlangt nur auf viele verschiedene Arten nach Ärger. In 99,9% der Fälle gibt es einen anderen, natürlicheren Weg. Ich werde hier eine wilde Vermutung anstellen und vorschlagen, dass der Fall des Fragestellers nicht in die verbleibenden 0,1% fällt.
Shylent
2
Tatsächlich ist es manchmal sehr angebracht, ein Array in einem Feld in einer Datenbank zu speichern. Ein Beispiel wären Metadaten wie eine globale 'Variablentabelle', in der System-Plugins und -Module ihre verschiedenen Einstellungen speichern können. Eine Tabelle, in der beliebige Sitzungsdaten gespeichert sind, kann am besten mithilfe eines Felds implementiert werden, das ein assoziatives Array von Schlüsseln / Werten enthält. serialize und unserialize (was die richtige Antwort ist) kümmern sich um Trennzeichen. Überprüfen Sie einige der mehreren erfolgreichen und beliebten Open-Source-Projekte wie WordPress oder Drupal - und Sie werden sehen, dass Arrays manchmal so in der
Datenbank
@ Scott Evernden: Ich denke du hast doch recht. PHP ist nicht meine "Hauptsprache", daher habe ich die Lösung aus der Perspektive des Datenbankdesigns beurteilt. Wenn das, was Sie beschreiben, wirklich die übliche Art ist, solche Dinge zu tun (in PHP), dann sei es so. Das gefällt mir aber nicht :)
Shylent
5
Es ist NIEMALS angebracht, ein Array in einem Feld in einer Datenbank zu speichern. Es ist eine Verletzung nicht der vierten Normalform, der dritten Normalform oder sogar der zweiten Normalform: Es ist eine VERLETZUNG DER ERSTEN NORMALEN FORM. Wenn Sie sich nicht einmal an die erste normale Form halten können, stimmt etwas mit Ihrer Bewerbung nicht. Das gilt für Drupal und Wordpress. Wenn sie dies tun, liegt das sicherlich nicht daran, dass diese Facette ihrer Apps gut gestaltet ist. Ich hatte dieses Argument bei meinem letzten Job, und weil XCart diesen Unsinn machte, machte es etwas möglich, das möglich gewesen wäre, stattdessen äußerst schwierig.
Dexygen
2

Sie können Ihr Array als JSON speichern.
Es gibt eine Dokumentation für den json-Datentyp: https://dev.mysql.com/doc/refman/5.7/en/json.html
Ich denke, dies ist die beste Lösung und hilft Ihnen, Ihren Code besser lesbar zu halten, indem Sie verrückte Funktionen vermeiden .
Ich gehe davon aus, dass dies für Sie hilfreich ist.

Roberto Murguia
quelle
0

Ja, serialisieren / unserialisieren ist das, was ich in vielen Open Source-Projekten am meisten gesehen habe.

Eduardo
quelle
0

Ich würde vorschlagen, implode / explode mit einem Zeichen zu verwenden, von dem Sie wissen, dass es in keinem der einzelnen Array-Elemente enthalten ist. Speichern Sie es dann in SQL als Zeichenfolge.

user1478500
quelle
3
Diese Frage wurde vor 3 Jahren gestellt und hat eine akzeptierte Antwort. Möglicherweise ist es hilfreicher, neuere Fragen oder Fragen ohne Antworten zu beantworten.
MDrollette
0

Schauen Sie sich die Implodierungsfunktion an, da sich die Werte in einem Array befinden. Sie möchten die Werte des Arrays in eine MySQL-Abfrage einfügen, die die Werte in eine Tabelle einfügt.

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

Wenn die Werte im Array Textwerte sind, müssen Sie Anführungszeichen hinzufügen

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

mysql_query($query);

Wenn Sie keine doppelten Werte wünschen, schalten Sie "INto" auf "IGNORE" und es werden nur eindeutige Werte in die Tabelle eingefügt.

j0k
quelle
Wenn Sie einen Primärschlüssel haben, erhalten Sie mit INSERT INTO ohnehin keine Duplikate. Wenn Sie keinen Primärschlüssel oder Index haben, macht IGNORE keinen Unterschied.
Peter Lindqvist
0

Sie können ein serialisiertes Objekt (Array) in ein serialize($object)MySQL-Beispiel einfügen und ein Beispiel für ein unserize-Objekt erstellenunserialize($object)

Vildan Bina
quelle
-5

Anstatt es in der Datenbank zu speichern, speichern Sie es in einer Datei und rufen Sie es später auf.

Viele PHP-Apps (wie Sugarcrm) verwenden einfach var_export, um alle Daten des Arrays in eine Datei zu übertragen. Folgendes speichere ich zum Speichern meiner Konfigurationsdaten:

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

Ich denke, dies ist ein besserer Weg, um Ihre Daten zu speichern!

AntonioCS
quelle
Es ist ein anderer Weg, nicht unbedingt besser.
Peter Lindqvist
Tatsächlich. Ich denke nur, dass der Zugriff auf die Datei viel einfacher ist, als die Datenbank abzufragen, um die Array-Daten abzurufen und dann das Array zu initialisieren. Auf diese Weise fügen Sie einfach die Datei ein und fertig.
AntonioCS