RSS Feed

Arrays und andere komplexe Daten mit PHP in einer MySQL-Datenbank speichern

Veröffentlich am Sonntag, 24. Jan 2010 in Webentwicklung

Viele von euch werden wohl schon einmal vor dem Problem gestanden haben, dass sie ein Array oder ein Objekt in der Datenbank speichern mussten. Hier möchte ich ein paar Vorschläge unterbreiten, wie man das Problem nicht lösen sollte und wie es besser gehen kann.

Der schlechte Weg

Die einfachste und gleichzeitig auch schlechteste Methode wäre es, für jeden Index eines Arrays oder jede Eigenschaft eines Objekts eine neue Spalte zu erzeugen. Bei diesem Ansatz werden unter Umständen viele Zeilen erzeugt, die nicht immer einen Wert enthalten. Das ist zwar nicht so gravierend, aber durch diesen Ansatz erhöht sich auch die Anzahl der Spalten schnell auf eine unübersichtliche Anzahl. Zuletzt ist es hierbei bei jeder Änderung des Arrays oder Objekts notwendig die Datenbanktabelle anzupassen.

Eine bessere Lösung gefällig?

Etwas besser Lösung, die fast immer funktioniert aber nicht für alle Fälle optimal ist, wäre eine Serialisierung des Arrays oder Objekts. Hierbei werden die Daten mit der serialize() Funktion in einen String konvertiert und können somit direkt in eine VARCHAR oder TEXT Spalte speichert werden. Dabei muss der String natürlich noch durch die Funktion real_escape_string() (in diesem Beispiel von der MySQLi Klasse) “escaped” werden.

Speichern der Daten

// Das zu speichernde Array
$array = array('vorname' => 'Max', 'name' => 'Mustermann');
// Serialisieren der Daten
$string = serialize($array);
// Speichern der Daten
$mysqli->query('INSERT INTO table_name (array) VALUES ("'.$mysqli->real_escape_string($string).'")'))

Das Beispiel setzt natürlich voraus, dass die Variable $mysqli eine Instanz der MySQLi Klasse mit einer gültige Verbindung zu einer Datenbank enthält. Wir haben hier ein einfaches assoziatives Array, das serialisiert wird und anscheinend gespeichert wird. Die serialisierten Daten sehn in diesem Beispiel wie folgt aus:

Der zu speichernde String

a:2:{s:7:"vorname";s:3:"Max";s:4:"name";s:10:"Mustermann";}

Das Auslesen der Daten wird mit der Funktion unserialize() durchgeführt, die aus dem String wieder ein assoziatives Array erzeugt. Dazu lesen wir zuerst die Daten mit einem gewöhnlichen Query aus und konvertieren anschließend die Daten:

Auslesen der Daten

// Auslesen der Daten
$result = $mysqli->query('SELECT array FROM table_name');
$row = $result->fetch_assoc();
$string = $row['array'];
// Unserialisieren der Daten
$array = unserialize($string);

Diese Methode zum Speichern von komplexen Daten funktioniert recht gut, aber der serialisierte String benötigt dabei mehr Speicherplatz als für ein normales assoziatives Array eigentlich nötig wäre. Wie es eleganter geht zeige ich euch im nächsten Beispiel.

Die elegante Lösung mit JSON

Das Format JSON entspringt zwar der Skriptsprache JavaScript, aber es wird zu Zeiten von AJAX sehr oft auch serverseitig verwendet und erzeugt. Da die meisten serverseitigen Sprachen also auch JSON unterstützen bietet es sich auch für die Speicherung von komplexeren Datenstrukturen an. Die Anpassung des vorherigen Quellcodes beschränkt sich dabei auch auf eine einzige Zeile. Wir ersetzen lediglich die serialize() durch die json_encode() Funktion. Die Zeile 6 aus dem vorherigen Quellcode sieht dann folgt aus:

Speichern der Daten

...
$string = serialize($array);
...

Hierbei werden die Datei des assoziativen Arrays in die JSON Notation konvertiert. Hierbei ist der resultierende String kompakter als bei der Serialisierung, da die Länge der einzelnen Arraywerte nicht und Datentypen nicht gespeichert werden:

Der zu speichernde String

{"vorname":"Max","name":"Mustermann"}

Beim Lesen der Daten aus der Datenbank müssen sie dann selbstverständlich auch wieder in das ursprüngliche Format zurück konvertiert werden. Dabei kommt wie ihr schon vermutet die Funktion json_decode() zum Einsatz. Diese erzeugt aber normalerweise ein Standard-Objekt. Um das in unserem Beispiel verwendete assoziative Array zu erhalten, wird als zweiter Paramater “true” übergeben. Der Änderung am Quellcode aus dem vorherigen Beispiel sieht dann wie folgt aus:

Auslesen der Daten

...
$array = json_decode($string, true);

Die Verwendung von JSON sichert nicht nur die Daten sondern auch die Schlüssel eines Arrays. Dabei spielt es keine Rolle, ob das Array assoziativ ist oder Zahlen als Schlüssel verwendet. Auch wird die Sortierung dabei nicht verändert. Wer lediglich die Werte eines Array speichern möchte, also keine Schlüssel benötigt, kann auch einen noch einfacheren Weg gehen.

Array in der Datenbank light

Der einfachste Werte mehrere Daten eines Array in einer Datenbank zu speichern sind die Funktionen explode() und implode(). Hierbei werden die einzelnen Werte des Arrays durch den “Delimiter”, den man als ersten Parameter angibt voneinander getrennt bzw. miteinander verbunden. Auch bei dieser Variante müssen in den beiden Beispiel-Quellcodes nur die Funktionen für die Umwandlung ausgetauscht werden. Zu beachte ist hierbei, dass der “Delimiter” nicht in den Werten vorkommen darf. Wer also beispielsweise ein Array mit Datumsangaben im Format 2010-01-23 mit implode verbinden möchte, darf nicht den Bindestrich als “Delimiter” verwenden.

Die Werte können wie auch zuvor in einer VARCHAR oder TEXT Spalte gespeichert werden. Sehr hilfreich sind die beiden Funktionen aber auch beim Speichern in einer Spalte mit dem Spaltentyp SET. Da hierbei aber die Werte zusätzlich von Anführungsstrichen umgeben sein müssen, muss der “Delimiter” auch die Anführungsstriche enthalten. Die implode Funktion würde in der Speicherfunktion dann wie folgt eingesetzt:

Speichern der Daten in einer SET Spalte

...
$string = implode('", "', $array);
...

Fazit

Wie ihr also seht, gibt es viele Wege komplexere Daten in einer Datenbank zu speichern. Das Beispiel mit JSON als Repräsentation sollte in jeder serverseitigen Skriptsprache funktionieren, die JSON unterstützt. Solltet ihr PHP verwenden müsst ihr natürlich auch sicherstellen, dass JSON bei euch aktiviert ist. Am einfachsten geht das wie immer mit Hilfe der phpinfo() Funktion, die in der Ausgabe einen “json” Abschnitt haben sollte.

Diejenigen von euch, die einen WordPress Blog haben und sich schon einmal die Datenbanktabelle angesehen haben, werden vermutlich die JSON Strings schon gesehen haben. Den WordPress speichert z.B. Arrays eines Plugins automatisch in der JSON Notation in der “options” Tabelle ab. Das macht es einem Pluginentwickler sehr einfach das Array zu speichern.

Ich hoffe, dass euch das kleine Tutorial weiterhelfen oder auf neue Ideen bringen konnte. Über Anregungen würde ich mich wie immer sehr freuen.

  • Twitter
  • email
  • RSS
  • Facebook
  • MySpace
  • Google Bookmarks
  • MisterWong.DE
  • del.icio.us
  • LinkArena
  • Digg
  • Sphinn
  • Mixx
  • Reddit
  • Slashdot
  • Yigg
  • Technorati

Sei der Erste, der einen Kommentar hinterlässt

Hinterlasse einen Kommentieren

Impressum