PHP im Frühjahrsputz

Was ist neu in PHP 5.4?
Kommentare

Seit dem 1. März ist die PHP-Version 5.4.0 verfügbar. Wir stellen die neuen Features und Verbesserungen vor und zeigen, was durch die Neuerungen am eigenen Code zu beachten ist.

Am 1. März war es endlich soweit: Über zweieinhalb Jahre nach dem Release der Version 5.3.0 gaben die Release Manager der neuen Version, Stas Malyshev und David Soria Parra, die Verfügbarkeit der PHP-Version 5.4.0 bekannt. Mithilfe von acht Release Candidates bekam diese Version seit Mitte Oktober letzten Jahres ihren Feinschliff. Die Version 5.4.0 beinhaltet eine Menge großer neuer Features und kleinere Verbesserungen, ist schneller und schlanker, bringt aber auch eine Liste an Neuerungen mit sich, die Änderungen am eigenen Code bedingen können. Auch wenn die Liste der Neuerungen nicht sonderlich lang ist, haben sich doch einige Dinge getan. Nach dem Release der Version 5.3 wurde eigentlich an PHP 6 gearbeitet, wie auch diverse angekündigte, aber nie veröffentlichte Buchtitel verraten. Doch nach monatelanger Arbeit an einer grundsätzlichen Umstellung auf UTF-16 wurde dieser Weg aus unterschiedlichen Gründen verworfen. Viele andere Features sind geblieben und wurden für 5.4 und weitere 5.x beibehalten.

Frühjahrsputz

PHP 5.4 unterstützt oder benötigt die im Jahr 1999 veröffentlichte autoconf-Version 2.13, die nur wegen einer Handvoll Pakete überhaupt noch von den Distributionen bereitgestellt wird, nun nicht mehr. Unterstützt werden nun die Versionen ab 2.59, empfohlen werden 2.60 oder neuer. Letztere sollte in jeder modernen Linux-Distribution verfügbar sein, die Auswirkungen sind aber unkritisch und sollten nur die Hilfeausgabe des ./configure-Aufrufs betreffen. Das betrifft natürlich nur den Build-Prozess von PHP und ist für den Benutzer kaum von Bedeutung.

Zu beachten sind jedoch die weggefallenen Features und Optionen, wovon die am weitesten verbreiteten wohl die INI-Direktiven safe_mode (und alle daran angelehnten), magic_quotes_gpc, allow_call_time_pass_reference und register_globals/register_long_arrays waren, die allerdings alle schon in 5.3.0 als deprecated markiert worden waren. safe_mode stand schon lange in der Kritik, die Sicherheit zwar nur unwesentlich zu erhöhen, dabei aber ein falsches Bild von Sicherheit zu vermitteln und vor allem viele Probleme mit der Konfiguration zu verursachen. magic_quotes_gpc, register_globals und register_long_arrays hingegen waren im Sinne von Best Practices schon lange konsequent in den meisten Sammlungen abgeschaltet und ihre Nutzung weithin verpönt.

Die Liste der entfernten Funktionen beschränkt sich auf folgende: define_syslog_variables(), import_request_variables(), session_register(), session_unregister() und session_is_registered() hängen alle grob mit der globalen Bereitstellung von Request-Variablen via register_globals und Konsorten zusammen und sind somit obsolet. Des Weiteren wurden diverse mysqli_*-Funktionen entfernt, aber nicht alle. Weiterhin benutzen die MySQL-Erweiterungen mysql, mysqli und PDO_mysql jetzt standardmäßig die aktuelle mysqlnd Library. Die veraltete libmysql kann noch benutzt werden, muss jedoch mit einkompiliert werden.

Weiterhin erwähnenswert ist das Handling von Zeitzonen. Ohne die Angabe via date.timezone in der php.ini oder die Benutzung der Funktion date_default_timezone_set() wird die Zeitzone nicht mehr geraten, sondern UTC als Standardwert benutzt. Weiterhin entfällt der Support für putenv(„TZ=…“).

Die ältere sqlite2 Extension ext/sqlite wurde aus der Default-Installation entfernt, die deutlich häufiger genutzten Extensions ext/sqlite3 und ext/pdo_sqlite bleiben hiervon aber unberührt. Sie sind weiterhin im /pecl/-Ordner im Sourcecode zu finden (nicht zu verwechseln mit dem PECL Repository, in dem sie ursprünglich beheimatet waren).

Zur Abschaffung in der nahen Zukunft wurden die Funktionen mcrypt_generic_end() und mysql_list_dbs() als deprecated markiert. Außerdem ist 5.4 die letzte PHP-Version, für die Windows-Pakete für Windows XP und Windows 2003 bereitgestellt werden.

Definitiv nicht übersehen sollte man die durchaus sinnvolle Verwendung von UTF-8 als neuen Default-Wert der default_charset-INI-Direktive. Was so harmlos klingt, könnte bei falscher Konfiguration von Webserver oder Anwendung mittels Content-Type Header dazu führen, dass Besucher kaputte Umlaute zu sehen bekommen. Nah verwandt mit dieser Änderung ist eine der wenigen bisher aufgefallenen Unschönheiten an PHP 5.4. Bedingt durch diese Änderung des Default Charsets kann es zu unerwarteten Effekten mit htmlspecialchars()/htmentities() kommen, wenn man den -Parameter nicht setzt. Standardmäßig wird hier jetzt UTF-8 genommen. Um den früheren Default-Wert iso-8859-1 zu benutzen, kann man ihn natürlich weiterhin angeben. Problematisch wird es jedoch, wenn man default_charset wieder auf iso-8859-1 setzt und den $encoding-Parameter überhaupt nicht angibt. Dann wird nämlich der von PHP 5.4 vorgegebene Wert UTF-8 benutzt. Wenn man daran denkt, ist das aber schnell zu beheben. Den leeren String “ als $encoding zu übergeben, sorgt weiterhin dafür, dass versucht wird, das Encoding ausZend_Multibyte, default_charset und aktuellem locale zu ermitteln. Weitere, möglicherweise inkompatible Änderungen sind die break $var-Syntax (Konstrukte wie break 2 funktionieren aber weiterhin) und die Behandlung von nicht numerischen String Offsets (Listing 1).

bool(false)
bool(true)

Der Codeschnipsel in Listing 1 hätte mit PHP 5.3 noch genau jeweils das Gegenteil ausgegeben, also true/false für isset()/empty(). Es sind aber nicht nur Strings als Offsets betroffen, sondern auch Double-, Bool- und Null-Werte sorgen für E_NOTICE-Meldungen. String Offsets hingegen, die von PHPs Autocasting zu Integer-Werten gecastet werden können (also beispielsweise ‚12.3‘oder ‚5 foo‘), generieren zwar eine E_NOTICE, werden aber dennoch zu 12 beziehungsweise 5 konvertiert und „funktionieren“ somit. Die Verwendung von Superglobals als Parameternamen, wie etwa im folgenden Beispiel, führt jetzt zu einem Fatal Error bei der bisher möglicherweise unbemerkten Konvertierung von Arrays in einen String (was zu einem String mit dem Inhalt Array führte):


Generiert die Konvertierung jetzt zusätzlich eine E_NOTICE, bleibt das Verhalten aber aus Gründen der Rückwärtskompatibilität erhalten.

Die Verwendung von array_combine(array(), array()) ergibt jetzt, wie man wohl erwarten würde, ein leeres Array statt FALSE, und das Setzen einer Property auf einer Variable, die NULL, false oder ein leerer String ist, führt zu E_WARNING, statt E_STRICT.

Der Error-Level E_ALL beinhaltet jetzt standardmäßig E_STRICT; eine der am heftigsten diskutierten Änderungen, obwohl auch hier den Entwicklern seit Jahren empfohlen wird, mit maximalem Error-Level zu entwickeln, um keine noch so harmlos erscheinenden Warnungen zu übersehen. Problematisch wird es hier, wenn entgegen anderslautender Empfehlungen etwa die Optiondisplay_errors=On im Livebetrieb gesetzt ist und die jetzt in E_ALL enthaltenen E_STRICT-Warnungen dargestellt werden.

Eine immer prominenter auftretende Tendenz in Diskussionen auf der Entwickler-Mailingliste ist es, möglichst keine grundlegenden Verhaltensweisen der PHP Engine für den Benutzer konfigurierbar zu machen. Das dient nicht dem Einschränken der Funktionalität, sondern nur der Vermeidung von Überraschungen, etwa dass Anwendungen komplett anders reagieren, je nachdem wie die benutzte php.ini aussieht. Die oben genannten Direktiven magic_quotes_gpc und register_globals waren hier der wichtigste Schritt, aber auch y2k_compliance, session.bug_compat_42 und session.bug_compat_warn wurden in diesem Zuge abgeschafft.

[ header = Seite 2: Die wichtigsten Features]

Die wichtigsten Features

Das am längsten diskutierte Feature sind die so genannten Traits. Sie wurden schon 2008 von Stefan Marr unter dem Stichwort „Horizontal Reuse“ vorgeschlagen und mussten sogar zwei RFCs und diverse lange Diskussionen auf der Internals-Mailing-Liste überstehen. Steve Cook wird der Satz „Multiple inheritance is good, but there is no good way to do it.“ zugeschrieben, und Traits sind der Idee geschuldet, Mehrfachvererbung so zu implementieren, dass die Vorteile die Nachteile überwiegen [1]. Details zur Traits-Implementierung sind unter [2] zu finden. Als Beispiel mag hier eine Reihe von Klassen dienen, die alle gewisse Aktionen mitloggen können sollen, aber keine Vererbungshierarchie teilen und somit dieselbe Funktionalität entweder duplizieren oder kapseln müssten (Listing 2).

debug("starting engine");
}
}

class Foo extends Two {
use logging;

public function something() {
// do stuff
$this->warn("oops");
}
}

(new Car)->startEngine();
(new Foo)->something();
?>

PHP 5.4 hat auch endlich einen internen Webserver bekommen, der in der Entwicklung gute Dienste leisten kann. Er sollte aber allein schon aus Performancegründen nicht produktiv eingesetzt werden, da der Webserver alle Requests nacheinander behandelt (also auch eingebundene Stylesheets, Grafiken und JavaScript-Dateien). Es ist auch zu vermuten, dass dieses neue Feature im Releasezyklus nicht so stark getestet wurde, wie die Änderungen, die im Betrieb der eigenen Anwendung auf der neuen Version benutzt werden. Auch die Dokumentation empfiehlt explizit keinen Produktiveinsatz.

Aufgerufen wird der interne Webserver auf der Kommandozeile mit dem Befehl php -S hostname:port. Hierbei dürfte hostname:port im Normalfall wohl so etwas wie localhost:81 sein. Damit der Webserver aber auch von außen erreichbar ist, kann auch 0.0.0.0:81 benutzt werden. Dabei wird dann das aktuelle Verzeichnis als DocumentRoot benutzt, das kann jedoch alternativ mit dem Argument -t  beim Start explizit gesetzt werden. Außerdem ist es möglich, ein PHP-Skript als letztes Argument anzugeben, das einen minimalen Front Controller abbildet. Hierzu zeigt Listing 3 ein Beispiel aus der Dokumentation.

<?php
// router.php
if (preg_match('/.(?:png|jpg|jpeg|gif)$/', $_SERVER["REQUEST_URI"]))
return false;
else {
echo "

Welcome to PHP

"; } ?>

Dateien, die laut ihrer Dateiendung Bilder sind, werden hier direkt ausgeliefert, ansonsten wird einfach Inhalt zurückgegeben. Das kann via direkter Ausgabe oder include/require geschehen. Kompliziertere Setups, wie in Anwendungen mit vielen mod_rewrite, dürften sich mit einem gewissen Aufwand portieren lassen. Leider gibt es hier aber noch keine allgemein bekannte, schnelle Lösung. Doch da die meisten aktuellen Frameworks sowieso im DocumentRoot alle Aufgaben von der index.php erledigen lassen, sollte sich der Aufwand in Grenzen halten.

Der Webserver gilt als eigenes SAPI (Server API) mit dem Namen cli-server, gilt vom Verhalten her aber auch als CLI Binary und benutzt somit nicht dieselbe php.ini wie das üblicherweise im Webserver eingesetzte CGI/FastCGI Binary. Die Option -c beim Start ermöglicht es aber auch hier, die gewünschte php.ini zu verwenden. Hier kann via cli_server.color auch eine farbige Ausgabe am Kommandozeilen-Prompt aktiviert werden. Weiterhin unterstützt PHP eine kurze Array-Syntax ähnlich der von JavaScript oder anderen Sprachen. Auf die Einführung von : statt => wurde jedoch verzichtet, die []-Notation kann einfach als Kurzform von array() verstanden werden (Listing 4).

 1, 'b' => 2];
?>

Weitere Features

Des Weiteren kamen eine Menge kleinerer Features hinzu, die im Großen und Ganzen das Leben eines PHP-Programmierers vereinfachen können. Es gibt jetzt den Typehint callable, der solche Parameter zulässt, die dieselben Kriterien erfüllen, die auch die Funktion is_callable() prüft. Das sind meist Closures und Strings, die Funktionsnamen beinhalten, aber auch die Array-Notation in der Form array(‚Klasse‘, ‚Methode‘) oder array($objekt, ‚Methode‘) wird unterstützt. Das Ganze dient der vereinfachten Behandlung von Closures ohne zusätzliche Aufrufe von is_callable() (Listing 5). Wie erwartet wird „Hello, World!“ ausgegeben. Dieses „Array Dereferencing“ funktioniert aber natürlich auch, wenn ein assoziatives oder gemischtes Array zurückgegeben wird.


Binärzahlen können, ähnlich wie Hex-Zahlen in der Form 0x2a geschrieben werden können, nun in der Form 0b101010 geschrieben werden. Die Kurzform <?= von <?php echo ist jetzt immer verfügbar, nicht nur wenn die unbeliebte short_open_tag-INI-Direktive gesetzt ist. Hintergrund war, dass der PHP-Parser <? fälschlicherweise als PHP-Code interpretieren konnte, wie etwa das in XML-Dateien anzutreffende <?xml. Mit <?= besteht dieses Problem jedoch nicht, daher steht dieser Änderung nichts im Weg. Die in 5.3 eingeführten Closures unterstützen jetzt die Verwendung der Variable $this, und die Verwendung des Hacks in Listing 6 kann man sich sparen. Hinzugekommen ist auch die Funktion hex2bin(), die Umkehrung der schon seit PHP 4 verfügbaren bin2hex()zur Konvertierung von Binärdaten in Hexadezimal-Repräsentation.


Die berühmt berüchtigte Fehlermeldung mit dem internen Token T_PAAMAYIM_NEKUDOTAYIM – selbst ein Wortwitz des „doppelten Doppelpunktes“ – und dem Operator :: bei Klassen und Methoden sowie einige andere Fehlermeldungen haben aussagekräftigere Beschreibungen bekommen, wurden aber nicht komplett geändert. Die INI-Direktive zend.multibyte ersetzt die Kompilierung mit –enable-zend-multibyte, der Support ist nun standardmäßig vorhanden und kann über die php.ini an- und ausgeschaltet werden. In der PHP CLI kam der Parameter –rz  hinzu, der Informationen über die genannte Zend Extension anzeigt. Bei Benutzung der interaktiven readline CLI (bei Aufruf von PHP mit der Kommandozeilenoption -a) kann man mittels #inisetting=value die Konfiguration zur Laufzeit ändern.

Die Funktionen debug_backtrace() und debug_print_backtrace() haben einen optionalen Parameter $limit bekommen, der die Anzahl der zurückgegebenen Stack Frames beschränkt, falls eine positive Zahl übergeben wird. Die Funktion is_link() funktioniert nun auch für symbolische Links unter Windows ab Vista. Die OpenSSL Extension hat Support für AES bekommen, außerdem diverse Bugfixes und Optionen. Leider ist sie aber immer noch größtenteils undokumentiert. Die Funktionen idn_to_ascii() und idn_to_utf8() aus ext/intl zur Konvertierung von Umlaut-Domains haben je zwei neue optionale Parameter zur Angabe der zu benutzenden Variante (IDNA 2003 oder UTS #46) und zur eventuellen Rückgabe von Details bei letzterer bekommen. Für den Großteil der PHP-Entwickler (unter Linux und Windows) leider nicht sehr hilfreich, für Solaris-, OS X- und FreeBSD-Benutzer jedoch verfügbar, ist der Support von DTrace in PHP. Unerwähnt bleiben soll hier aber die Behebung zahlreicher Bugs. Eine Liste befindet sich jedoch im PHP5 Changelog auf php.net.

Neue Prozesse

Nicht nur am Code, auch am Entwicklungsprozess hat sich seit 5.3 so viel getan, wie zuvor lange nicht. Das ist das erste Release, das laut dem Release Process RFC (Request for Comments) veröffentlich wurde. Das erlaubt grundsätzlich inkompatible Änderungen in den internen Strukturen, die API-Kompatibilität muss aber gewährleistet sein. Das bedeutet, dass für den Benutzer keine Änderungen an Methodensignaturen (beispielsweise Vertauschen von Parametern) anfallen dürfen. Weiterhin dürfen nach dem Release der 5.4.0 in den nachfolgenden 5.4.1, 5.4.2 etc. keine größeren Features eingebaut werden. Wie immer gilt hier jedoch, dass in dringenden Fällen und nach Abstimmung und Rücksprache, Ausnahmen möglich wären. Erlaubt ist weiterhin das Entfernen von Extensions aus der Standardinstallation.

Das ist auch das erste Release mit einem festgelegten Zyklus, wie lange dieser Branch aktiv weiterentwickelt und mit Bugfixes versehen wird (zwei Jahre), um danach in einen Status überzugehen, der nur sicherheitskritische Bugfixes enthält und ein Jahr dauert. Der Support für den Zweig 5.4 sollte damit am 1. März 2015 enden. Im Zuge dessen läuft gerade die Diskussion, wann der Support für 5.3 eingestellt werden soll, da dieser Zweig vor der Ratifizierung des Release Process RFC veröffentlicht wurde und somit noch nicht abgedeckt ist. Die Mehrheit der PHP-Core-Entwickler vertreten die Ansicht, dass grundsätzlich nichts gegen einen längeren Support älterer Versionen von PHP spräche. Aus Zeitgründen seien jedoch nicht mehr als zwei Versionen vertretbar (eine in aktiver Entwicklung, eine in Bugfix-only-Phase), und die Verfügbarkeit so genannter Long-Time-Support-(LTS-)Versionen sollte den Betriebssystem-Distributionen überlassen werden. Daraus lässt sich auch schließen, dass der Support für PHP 5.3 wahrscheinlich eingestellt wird, sobald PHP 5.5 veröffentlich wird.

Aus organisatorischer Sicht kommt dem Release-Manager-(RM-)Team die Aufgabe zu, den Ablauf des Release anhand einer Roadmap zu planen und den Prozess in Anlehnung daran durchzuführen. Das beinhaltet vor allem die Entscheidungsgewalt darüber, die Release-Candidate-(RC-)Phase zu starten und zu überwachen. Es liegt aber nicht an ihnen zu entscheiden, welche Features zu Beginn der RC-Phase noch in das kommende Release einfließen können und welche noch nicht reif genug sind. Auch dies wird öffentlich abgestimmt. Im Gegensatz zur Vergangenheit soll es immer zwei Release Manager je Version geben, die durch öffentliche Abstimmung im normalen Vorschlags- und RFC-Prozess gefunden werden sollen, wie es auch für 5.4 schon passiert ist.

Fazit

Sollte man seine Anwendung nach Best-Practices-Regeln für PHP 5.3 geschrieben haben, dürften nur wenige Inkompatibilitäten auftreten. Details verrät hier der durchaus ausführliche PHP 5.4 Migration Guide auf php.net. Insgesamt sind es weniger weitschweifende Änderungen, als der Umstieg von PHP 5.2 auf 5.3 mit sich brachte. Für die Anwendungen, die noch nicht einmal für PHP 5.2 fit gemacht wurden, ist der Aufwand jedoch erwartungsgemäß noch ein bisschen größer. Dennoch sollte nicht vergessen werden, dass der Zweig PHP 5.2 schon seit 2011 nicht mehr aktualisiert wird und eine Migration dringend anzuraten ist. Obwohl die Aufmerksamkeit der PHP-Entwickler im März durchaus auf den Umzug der Sourcecode Repositories von Subversion [3] auf GIT [4] gelenkt war, war die Stimmung seit dem Release der Version 5.4.0 durchaus positiv, und bisher sind keine Showstopper bekannt geworden. Am 30.03.2012 wurde mit dem Releasezyklus der Version 5.4.1 begonnen, die hauptsächlich Bugfixes enthält, die es nicht mehr in die Version 5.4.0 geschafft haben, aber auch solche, die erst danach auffielen.

Unsere Redaktion empfiehlt:

Relevante Beiträge

Meinungen zu diesem Beitrag

X
- Gib Deinen Standort ein -
- or -