(PHP): iniToArray()

Problematik

Jede Webanwendung benötigt Konfigurationsdaten. Dabei entsteht natürlich das Problem, in welcher Form die Konfigurationsdaten gespeichert werden sollen. Eine Möglichkeit ist das klassische Windows-INI-Format. Bei diesem Format werden die Konfigurationsdaten in der Form:
name = wert
zeilenweise notiert. Dazu können jedoch noch Zeilen kommen, die Sektionsüberschriften enthalten. Solche Zeilen haben die Form:
[Sektionsname]
Unterhalb einer Sektionsüberschrift notierte name=wert-Paare gehören dann zur betreffenden Sektion.
In PHP ist es mit Hilfe einer kleinen Funktion möglich, eine solche Datei in einen assoziativen PHP-Array einzulesen.

Code

<?php
 
function iniToArray($iniFile = NULL) {
   if($iniFile == NULL or !file_exists($iniFile) or !is_file($iniFile) or !is_readable($iniFile))
      return(FALSE);
   $lines = file($iniFile, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
   $iniArray = array();
   $section = "";
   foreach($lines as $line) {
      $line = trim($line);
      if(preg_match("/\[(.*?)\]/", $line, $match))
         $section = preg_replace("/[^a-z0-9\\.\\_]/i", "", $match[1]);
      if(strstr($line, "=") !== FALSE) {
         list($name, $value) = explode("=", $line);
         $name = trim($name);
         $name = preg_replace("/[^a-z0-9\\.\\_]/i", "", $name);
         $value = trim($value);
         if($section !== "")
            $iniArray[$section][$name] = $value;
         else
            $iniArray[$name] = $value;
      }
   }
   return($iniArray);
}
 
?>

Erläuterung

Die Funktion iniToArray() bekommt als Parameter den Pfad-/Dateinamen der einzulesenden INI-Datei übergeben. Sie prüft zunächst, ob der Parameter übergeben wurde, ob die Datei existiert, ob es eine Datei ist, und ob sie lesbar ist. Im Fehlerfall wird FALSE zurückgegeben.

Mit der PHP-Standardfunktion file() wird die INI-Datei zeilenweise in den Array $lines eingelesen. Dieser Array wird in der foreach-Schleife abgearbeitet, die sich an die Initialisierung des Rückgabe-Arrays $iniArray und der Variablen $section für aktuelle Sektionsüberschriften anschließt.

Mit trim() werden zunächst eventuelle Leerraumzeichen am Anfang und Ende der Zeile entfernt. Dann wird mit preg_match() überprüft, ob die aktuell abzuarbeitende Zeile eine Sektionsüberschrift enthält. Wenn ja, wird die Variable $section mit der Sektionsüberschrift versorgt. Dabei werden allerdings mit preg_replace() alle Zeichen entfernt, die keine ASCII-Buchstaben, Ziffern oder Unterstrich sind. Denn die Sektionsüberschrift soll ja im Rückgabe-Array als Schlüssel dienen.

Danach wird mit strstr() geprüft, ob die aktuell bearbeitete INI-Zeile ein name=wert-Paar darstellt. Mit explode() werden Name und Wert getrennt in die Variablen $name und $value gespeichert. Beide Daten werden noch mal mit trim() behandelt, um auch die Leerzeichen, die üblicherweise um das Istgleichzeichen notiert sind, zu eleminieren. Auf $name wird außerdem wie schon auf $section die Prozedur zum Entfernen von Zeichen angewendet, die nicht im Array-Schlüssel vorkommen sollen.

Zuletzt wird die bearbeitete Zeile zu einem Eintrag im Rückgabe-Array. Wenn $section nicht leer ist, wird ein Eintrag auf zweiter Ebene erzeugt ($iniArray[$section][$name]), andernfalls ein Eintrag auf oberster Ebene ($iniArray[$name]). Der so erzeugte Array wird nach Beenden der foreach-Schleife zurückgegeben.

Nehmen wir als Beispiel folgende INI-Datei:

[boot loader]
timeout=30
default=multi(0)disk(0)rdisk(0)partition(1)\WINDOWS
[operating systems]
multi(0)disk(0)rdisk(0)partition(1)\WINDOWS="Microsoft Windows XP Professional Edition" /fastdetect

Daraus erzeugt unsere Funktion folgenden Array (hier so wiedergegeben, wie es die PHP-Funktion var_dump() tun würde:

array(2) {
  ["bootloader"]=>
  array(2) {
    ["timeout"]=>
    string(2) "30"
    ["default"]=>
    string(43) "multi(0)disk(0)rdisk(0)partition(1)\WINDOWS"
  }
  ["operatingsystems"]=>
  array(1) {
    ["multi0disk0rdisk0partition1WINDOWS"]=>
    string(47) ""Microsoft Windows XP Professional Edition" /fastdetect"
  }
}
page_revision: 3, last_edited: 1214510259|%e %b %Y, %H:%M %Z (%O ago)