PHP: ini-file-reader

(Kommentare: 0)

Mit der PHP-Funktion parse_ini_file hatte ich in PHP 5.2 und 5.3 so meine Probleme. Auf Basis eines in der PHP-Online-Doku beschriebenen Tokenizers habe ich mir dann eine eigene Lösung zusammengeschraubt.

Vielleicht kann sie noch jemand gebrauchen.

<?php

/** Utility to parse an ini file (does actually the same as parse_ini_file() but more
  * stable). Note: does not replace placeholders like ${name} like new php versions do.
  *
  * Usage: IniReader::readIni($file);
  *
  * @author Ingmar Decker (www.webdecker.de)
  */
class IniReader {

    public static function readIni($file, $sections = TRUE, $verbose = FALSE) {
        $data = array();
        if (file_exists($file)) {
            $contents = file_get_contents($file);
            $tokens = IniReader::getTokens($contents, $verbose);
            if ($tokens) {
                $data = array();
                $section = null;
                foreach ($tokens as $token) { 
                    if (isset($token['section'])) {
                        $section = $token['section'];
                        continue;
                    }
                    if (isset($token['key'])) {
                        $key = $token['key'];
                        $value = null;
                        $type = null;
                        foreach ($token as $k => $v) { 
                            if ($k != 'key') { 
                                $value = $v; $type = $k; break; 
                            } 
                        }
                        if ($value == 'true') { $value = true; }
                        else if ($value == 'false') { $value = false; }
                    
                        #if ($value && defined($value)) eval('$value = ' . $value . ';');
                        if (substr($key, strlen($key)-2) == '[]') {
                            $key = substr($key, 0, strlen($key)-2);
                            if ($section) { 
                                if ($value === null) {
                                    if (!isset($data[$section][$key])) $data[$section][$key] = array();
                                } else {
                                    $data[$section][$key][] = $value;
                                }
                            } else {
                                if ($value === null) {
                                    if (!isset($data[$key])) $data[$key] = array();
                                } else {
                                    $data[$key][] = $value;
                                }
                            }
                        } else {
                            if ($section) {
                                $data[$section][$key] = $value;
                            } else {
                                $data[$key] = $value;
                            }
                        }
                    }
                }
            }
        } else {
            #throw new Exception("File $file does not exist");
        }

        
        return $data;
    }
    
    /** Got this code from http://de3.php.net/manual/de/function.parse-ini-file.php. */
    private static function getTokens($data, $verbose = FALSE) {
        $regexp = '/
        (?<=^|\r\n|\r|\n)
        (?P<line>
            (?:
                (?(?![\t\x20]*;)
                    (?P<left_space>[\t\x20]*)
                    (?:
                        \[(?P<section>[^;\r\n]+)\]
                        |
                        (?P<setting>
                            (?P<key>
                                [^=;\r\n]+?
                            )?
                            (?P<left_equal_space>[\t\x20]*)
                            (?P<equal_sign>=)
                            (?P<right_equal_space>[\t\x20]*)
                            (?P<val>
                                \x22(?P<quoted>.*?)(?<!\x5C)\x22
                                |
                                \x27(?P<apostrophed>.*?)(?<!\x5C)\x27
                                |
                                (?P<null>null)
                                |
                                (?P<bool>true|false)
                                |
                                (?P<int>[+-]?(?:[1-9]\d{0,18}|0))
                                |
                                (?P<float>(?:[+-]?(?:[1-9]\d*|0))\.\d+(?:E[+-]\d+)?)
                                |
                                (?P<string>[^;\r\n]+?)
                            )?
                        )
                    )
                )
                (?P<right_space>[\t\x20]*)
                (?:
                    (?P<comment_seperator>;)
                    (?P<comment_space>[\t\x20]*)
                    (?P<comment>[^\r\n]+?)?
                )?
            )
            |
            (?P<error>
                [^\r\n]+?
            )
        )
        (?=\r\n|\r|\n|$)(?P<crlf>\r\n|\r|\n)?
        |
        (?<=\r\n|\r|\n)(?P<emptyline>\r\n|\r|\n)
        /xsi';

        if (!@is_int(preg_match_all($regexp, $data, $tokens, PREG_SET_ORDER))) {
            // parse error
        } else {
            foreach($tokens as $i => $token) {
                if(!$verbose) {
                    unset($tokens[$i]['line']);
                    unset($tokens[$i]['crlf']);
                    unset($tokens[$i]['setting']);
                    unset($tokens[$i]['equal_sign']);
                    unset($tokens[$i]['val']);
                    unset($tokens[$i]['left_space']);
                    unset($tokens[$i]['left_equal_space']);
                    unset($tokens[$i]['right_equal_space']);
                    unset($tokens[$i]['right_space']);
                    unset($tokens[$i]['comment_seperator']);
                    unset($tokens[$i]['comment_space']);
                }
                foreach($token as $key => $val) {
                    if(!@is_string($key) || !@strlen($val)) {
                        unset($tokens[$i][$key]);
                    }
                }
            }
            return($tokens);
        }
    } 
}

?>



Ich finde das ini-Fileformat ganz nett und für meine aktuelles Zwecke war es praktisch, zumal es eine in PHP eingebaute Leseroutine gibt, wo ich davon ausging, dass die schnell läuft. Leider hatte ich skurrile Probleme mit den Anführungszeichen bzw. deren Escapen in PHP 5.2 und in PHP 5.3. hat's ständig gekracht, das hat mich genervt. So ist das hier entstanden.

Dank an den "in lexer weiter" auf http://de3.php.net/manual/en/function.parse-ini-file.php.

Zurück

Kommentare

Einen Kommentar schreiben