Nette v PHP 5.3

Upozornění: Tohle vlákno je hodně staré a informace nemusí být platné pro současné Nette.
fiso
Člen | 32
+
0
-

Ahoj,

nainštaloval som si najnovšie PHP 5.3–200807131230 a hodilo mi to pár chýb (ja viem že to nie je finálne 5.3, ale myslím, že stojí za to sa na to pozrieť).

Zdá sa, že sa novému phpčku nepáči protected pri magických funkciách (__get, __set, …), treba to prepísať na public.

Pri parse_ini_file sa mu nepáči, že sa používajú špeciálne znaky ako > alebo :, takže sa nedajú používať konfiguračné súbory. V starších verziách to pochopiteľne išlo. Možno by stálo za to, aby sa konktaktovali tvorcovia, nech s tým parse_ini_file moc nevymýšľajú.

Prípadné ďalšie chyby čo nájdem sem pridám.

fiso
Člen | 32
+
0
-

Tohto som sa bál:
http://bugs.php.net/bug.php?…
V changelogu:

  • Fixed bug #42069 (parse_ini_file() allows using some non-alpha numeric

    characters). (Jani)

Vyzerá to tak že túto „feature“ považujú za bug. Jediné rozumné riešenie je asi vlastný parser na INI súbory.

David Grudl
Nette Core | 8218
+
0
-

Máš recht, ale dokud se nebude blížit ostrá verze, je zbytečné na momentální nálady tvůrců reagovat.

fiso
Člen | 32
+
0
-

Nie som si celkom istý či opravenie bugu je možné označiť ako momentálnu náladu tvorcov PHP, uvidíme. Každopádne som potreboval spojazdniť INI súbory, takže tu je taký malý návod ako na to:

V triede ConfigAdapterIni (nette/Config/ConfigAdapterIni.php) v metóde load treba zameniť parse_ini_file za nasledovné volanie

$data = self::parseIniFile($file);

Potom treba doplniť do triedy túto metódu:

	/**
	 * PHP implementation of parse_ini_file function
	 * @param string
	 * @return array
	 */
	private static function parseIniFile($file)
	{
		$ini = file($file);

		// file has no contents
		if(count($ini) == 0) {
			return array();
		}

		$section = "";
		$result = array();
		$i = 0;

		foreach ($ini as $line) {
			$line = trim($line);
			$line = str_replace("\t", " ", $line);

			// Line comments
			if(preg_match('/^\s*;.*/', $line) || !$line) {
				continue;
			}

			// Sections
			if ($line{0} == '[') {
				$section = substr($line, 1, -1);
				$result[$section] = array();
				continue;
			}

			// Key-value pair
			list($key, $value) = explode('=', $line, 2);
			$key = trim($key);
			$value = trim($value);

			// Value parsing
			if($value{0} != '"' && $value{0} != "'") { // constant
				// trim comment, if any
				if(($pos = strpos($value, ";")) !== FALSE) {
					$value = substr($value, 0, $pos);
				}

				$value = defined($value) ? constant($value) : $value;
			} else { // string
				$escaping = 0;
				$broken = false;
				for($a = 1, $len = strlen($value); $a < $len; $a++) {
					if($value{$a} == "\\") {
						$escaping++;
					} elseif($escaping % 2 == 0) {
						$escaping = 0;
					}

					// terminate parsing
					if($value{$a} == "'" || $value{$a} == '"' && $escaping == 0) {
						$value = substr($value, 1, $a-1);
						$broken = true;
						break;
					}
				}
				if(!$broken) {
					$value = substr($value, 1);
				}
			}

			if($section) {
				$result[$section][$key] = $value;
			} else {
				$result[$key] = $value;
			}
		}

		return $result;
	}

Trochu okukané z http://sk.php.net/…ini-file.php a upravené, nie príliš otestované ale funguje fajn.

David Grudl
Nette Core | 8218
+
0
-

Pomohlo by použít jiný oddělovač ConfigAdapterIni::$keySeparator a to -. Parser v PHP 5.3 přežije ještě znaky _ a ., ale pokud chceš přes konfigurák nastavovat PHP direktivy způsobem

set> date.timezone = "Europe/Prague"
set> iconv.internal_encoding = "%encoding%"

zbývá skutečně jen pomlčka. Takže asi takto:

set-date.timezone = "Europe/Prague"
set-iconv.internal_encoding = "%encoding%"

Pokud se parser v PHP 5.3 nezmění, asi přidám podporu pro podsekce, nějak takto:

[common.variable]
tempDir = %appDir%/cache
foo = %bar% world
bar = hello

[common.set]
date.timezone = "Europe/Prague"
iconv.internal_encoding = "%encoding%"