PHP 5.3 Was ist neu?
Seit Ende Juni ist es endlich soweit. PHP released die Version 5.3 der erfolgreichen Skriptsprache. Natürlich gab es dazu auch einen einführenden Vortrag bei CosmoCode, den ich hier noch einmal kurz zusammenfassen möchte.
Der Sprung von 5.2 auf 5.3 lässt sich, gemessen an den Neuerungen, durchaus mit dem Sprung von PHP 4 auf PHP 5 vergleichen. PHP 5.3 ist nicht nur das schnellste PHP, es wurden auch viele Fehler behoben. Zu den Neuerungen auf die ich im Folgenden kurz eingehen werde zählen u.a. Namespaces, Late Static Binding und Phar Archive.
Namespaces
Bisher wurde versucht Eindeutigkeit von Klassen, Funktionen und Konstanten durch möglichst eindeutige Bezeichner zu erreichen die teilweise doch sehr lang werden konnten. Nun gibt es Namespaces. Das Prinzip ist vielleicht bekannt aus C++. Namespaces ermöglichen es Klassen, Konstanten oder Funktionen in einen eigenen Namensbereich zu stecken. Dadurch lässt sich externer Code einfacher in die eigene Umgebung einbinden, da keine Namenskonflikte/Überschneidungen entstehen können. Die Klassenbezeichner können dadurch kürzer ausfallen, was zu einer besseren Lesbarkeit des Quellcodes führt. Namespaces sind sehr intuitiv da man Baumstrukturen schon von Verzeichnissen aus dem alltäglichen Leben her kennt.
Namespaces waren schon für das Release von PHP 5.2 geplant, wurden aber in letzter Minute doch noch rausgenommen, da es Konflikte mit dem damaligen Separator “::“ gab. Nun hat man sich auf \ geeinigt. Hier ein Beispiel für solch einen voll qualifizierten Bezeichner:
\SomeProject\SubSpace\SubSubSpace\MyClass
Als Beispiel ließe sich eine Klasse MyClass aus dem Projekt MyProjekt ganz einfach verpacken in
namespace MyProject;
class MyClass
{
...
}
Auch das Importieren von Namespaces sowie das Anlegen von Aliases wird unterstützt:
namespace ExternProject
class MyClass
{
...
}
namespace MyProject;
use ExternProject\MyClass as OtherMyClass;
$obj = new OtherMyClass();
Beachtet werden sollte die Tatsache, dass auch Klassen, Funktionen und Konstanten von PHP selber einem Namespace angehören, dem globalen Namespace \
Hier zu sehen am Beispiel einer Exception:
try {
throw new \Exception("my exception"); // => use global namespace \
} catch ( Exception $ex) {
echo $ex->getMessage(); // => my exception
}
oder bei einer Funktion
echo \strlen("my string"); // => 9
Werden im eignen Projekt Namespaces eingesetzt, was sinnvoll ist, muss bei Verwendung der globalen Komponenten auch der globale Namespace verwendet werden.
Bei Funktionen gilt es ein Besonderheit zu beachten. Wird eine Funktion im aktuellen Namespace nicht gefunden gibt es einen Fallback auf den globalen Namespace. Folgendes wäre also äquivalent zu dem letzten Beispiel:
echo strlen("my string"); // => 9
hier wird zunächst im aktuellen Namespace gesucht. Wird diese Funktion nicht gefunden sucht PHP im globalen Namespace.
Um noch ein paar formale Dinge zu klären.
-
Mehrere Namespaces können in einer Datei definiert werden
-
Ein Namespace kann über mehrere Dateien hinweg definiert werden
-
Die Konstante __NAMESPACE__ so wie der Operator \namespace geben Auskunft über den aktuellen Namespace
-
Die Verwendung von Namespaces ist optional, verwendet man sie nicht bleibt alles beim Alten
Detaillierte Infos zu Namespaces gibt es unter http://php.net/namespace
Late-Static-Binding
Eine weitere Neuerung ist die Möglichkeit des Late-Static-Binding. Es ermöglicht ein elegantes Überschreiben statischer Methoden. Folgendes kennt man. Es wird eine zur Übersetzungszeit gebundene Klassenmethode aufgerufen.
self::MyMethod();
Verwendet man nun static:: anstelle von self:: ist es möglich die entsprechende Methode in einer abgeleiteten Klasse zu überschreiben. Die aufzurufende Methode wird dann erst zur Laufzeit gebunden:
class MyClass {
public static function MyText()
{
static::MyStaticMethod();
}
public static function MyStaticMethod()
{
echo "I LOVE you";
}
}
class MyExtendedClass extends MyClass
{
public static function MyStaticMethod(){
echo "I HATE you";
}
}
MyClass::MyText(); // => I LOVE you
MyExtendedClass::MyText(); // => I HATE you
In diesem Zusammenhang ist auch noch die neue Interzeptor Methode __callStatic() zu erwähnen, sozusagen das Äquivalent zur bekannten __call() nun für den static Scope.
class MyClass
{
static function __callStatic($method, $arguments) {
echo "You called method: $method with arguments: ".implode(',', $arguments);
}
}
MyClass::my_method(1, 2, 3) // => You called method: my_method with arguments: 1, 2, 3
Infos zum Late Static Binding gibt es unter http://php.net/lsb
PHAR - PHP Archiv
Eine größere hinzugekommene Extension ist PHAR in der Version 2.0.0. Die Basis von PHAR lieferte das PEAR Package „PHP_Archive“. Die neue PHP Extension beseitigt nun einige Probleme und kommt mit einem mächtigeren Funktionsumfang. PHP Applikationen können nun ohne größeren Aufwand in Form einer einzigen .phar Datei ausgeliefert werden. Das Konzept ist ähnlich der JAR Dateien von Java, jedoch sind bei PHAR keinerlei externen Programme zur Ausführung nötig - lediglich PHP. Hier eine kleine Featureaufzählung
-
ausführbare Archive mit Stub
-
Kompression(Tar, Zip) einzelner Dateien oder ganzer Archive, je nach unterstützter Kompression.
-
einfache Konvertierung zwischen Kompressionsmodi
-
Stream Wrapper(Dateien werden vor Benutzung nicht entpackt)
-
Digitale Signierung mit OpenSSL
Ein solches Archiv zu erzeugen ist fast schon trivial:
$myphar = new Phar('my_new_phar.phar');
$myphar['index.php'] = '<?php echo \'hello world\'; ?>'; // => create file 'index.php' with content "echo 'hello world';"
Achtung!! - PHP Archive können, sobald sie einen Stub besitzen oder die .phar Endung haben(also keine zip,tar Archive sind), nur dann erzeugt werden wenn folgender Parameter in der php.ini gesetzt ist.
phar.readonly = 0
Wer sich an dieser Stelle fragt “Wie war das jetzt mit Stub und Zip und Tar, wo liegen die Unterschiede“ schaut sich am besten die Vergleichstabelle auf http://php.net/manual/en/phar.fileformat.comparison.php an
Auch das Auslesen lässt sich leicht realisieren, bei folgendem Beispiel wird der Stream Wrapper phar:// verwendet:
echo file_get_contents('phar://myphar.phar/index.php');
Ein anderes Stream Wrapper Beispiel, hier wird eine Datei aus dem erstellten Archiv eingebunden:
include 'phar:///myproject/myphar.phar/index.php'; // => hello world
Archivaufbau
Ein Archiv besteht aus vier Komponenten
-
Stub
-
Manifest(permissions)
-
Content
-
[Signatur]
Die kurzen Beispiele sollten lediglich verdeutlichen wie einfach es ist die eigene Applikation zu verpacken. Nun möchte ich noch als kleinen Anreiz ein etwas komplexeres Beispiel vorstellen, welches aus einem Verzeichnis ein ausführbares Archiv erstellt und danach die Namen der enthaltenen Dateien(php, bilder, …) ausgibt.
$filename = 'myphar.phar';
$source = '/var/www/application';
@unlink($filename); // => delete old stuff
try {
$myphar = new Phar($filename, 0, 'myphar.phar'); // => create/open phar archiv
if ( !Phar::canWrite() ) {
throw new Exception('No write permissions!');
}
$myphar->startBuffering(); // => open transaction
$myphar->buildFromDirectory($source); // => set packet source
$myphar->setStub('<?php // => setup stub with proxy (executable archive)
Phar::interceptFileFuncs();
Phar::webPhar();
__HALT_COMPILER(); ?>');
$myphar->stopBuffering(); // => commit transaction
echo "created {$filename} successfully!";
} catch (UnexpectedValueException $e) {
die("open {$filename} failed");
} catch (BadMethodCallException $e) {
die('BadMethodCallException');
}
$myphar = new Phar($filename); // => create/open phar archiv
foreach (new RecursiveIteratorIterator($myphar) as $file) { // => print contained files
echo $file->getFileName(). "<br />";
}
Phar Archive im .phar Format, die einen Stub besitzen, also ausführbar sind, können auch in PHP Umgebungen ausgeführt werden die keine Phar Erweiterung installiert haben. Existiert in dem „gepackten“ Verzeichnis application(siehe $source in letztem Beispiel) eine index.php kann diese wie folgt on-the-fly ausgeführt werden:
www.mypage.de/myphar.phar/index.php
Hierfür muss beim Webserver natürlich der Application Type .phar auf php gemapped werden, oder die phar in myphar.php umbenannt werden.
Skaliert Phar?
Ich kann nicht aus eigener Erfahrung berichten, allerdings gibt es einige Leute die mit der Skalierung sehr zufrieden scheinen. Einige weisen darauf hin das Phar besonders gut skaliert wenn Byte Cacher z.B. APC verwendet werden.
Eine Übersicht über die Phar Erweiterung gibt es unter http://php.net/phar
zu guter Letzt
Es gibt noch weitere tolle Features wie z.B. Closures, Invokation oder eine effektivere Garbage Collection(interessant für Skripte die länger ausgeführt werden).
Ausführliche Infos zu PHP 5.3, und auch für die Umstellung von php 5.2 ⇒ PHP 5.3 bekommt man unter http://php.net/migration53.
Was erwartet uns bei PHP 6?
Alles was mit „Uni…“ anfängt und “..code“ endet 
In diesem Sinne, Danke für das Lesen meines ersten Posts, ich hoffe euer Interesse geweckt zu haben.