Details zu neuen PHP6 Features

Nach einer Recherche zu den (eventuell) kommenden Features und Neuerungen in PHP6, möchten wir hier nun auf einzelne Neuerungen und Features aus PHP6 näher eingehen.

Wie berichtet, soll es in PHP6 unter anderem

  • Unicode Unterstützung im Gegensatz zum bisherigen Binär-Strings Verfahren geben
  • Namespaces (Namensräume) eingeführt werden
  • register_globals abgeschafft werden
  • magic_quote ebenfalls
  • auch der safe_mode soll ausgemustert werden
  • die super globalen Variablen $HTTP_*_VARS entfernt werden
  • zuschaltbarer Input-Filter geben
  • die break Anweisung soll um ein Label erweitert werden (als Art goto-Konstrukt)
  • der konditionale Operator (Bedingung ? Wert : Alternativwert) soll auch mit leerem Wert verwendet werden können (Alternative zum ifsetor() Operator)
  • die Funktione microtime() soll nun immer ein float zurückgeben, nicht nur per microtime(true)

Was ist oder bedeutet nun diese ominöse Unicode Unterstützung in PHP6

Das lässt sich zunächst anhand eines Beispiels erklären. Ich denke, man kann dem Code ganz gut folgen:

declare(encoding = 'utf-8');
$foo = "héllo wörld";
var_dump($foo);         //PHP5: string(13) "héllo wörld" PHP6: unicode(11) "héllo wörld"
print strlen($foo);     //PHP5: 13                       PHP6: 11
print substr($foo,0,5); //PHP5: héll                     PHP6: héllo

Das dies eine Bereicherung ist, ist denk ich ganz klar. Strings wurden zwar bisher auch korrekt ausgegeben, aber dank Unicode Unterstützung werden sie in PHP6 auch richtig behandelt, hier am Beispiel der Stringlänge.
Dazu kommt, dass in Variablen- und Klassennamen nun sämtliche Unicode Zeichen erlaubt sind, also auch deutsche Umlaute etc.

Um eine gesicherte Abwärtskompatibilität zu PHP5 zu haben, wird Unicode per default erstmal deaktiviert sein und in der php.ini durch ein paar neue Optionen aktivierbar gemacht.

;aktiviert/deaktiviert Unicode in PHP
unicode_semantics = On|Off
;setzt das encoding des outputs, scripts, der Eingaben von außen, etc...
unicode.output_encoding
unicode.script_encoding
unicode.http_input_encoding
unicode.runtime_encoding
unicode.fallback_encoding

Was sind Namespaces, wem helfen sie in PHP6, wie setzt man sie ein, wo sind die Vorteile?

Allgemein erweitern Namespaces (Namensräume) die Anzahl möglicher Namen für Variablen und Klassen. In Java zum Beispiel sind Namespaces durch die Pakete (packages) umgesetzt.
Bisher in PHP gilt, wenn es eine Klasse Test_PHP6 gibt, und irgendwann in einem anderen Projekt eine weitere Klasse benötigt wird die man am liebsten auch Test_PHP6 nennen möchte, geht das nicht, man müsste sie Test_PHP6_2 oder Test_PHP6_Neu oder wie auch immer nennen.
In PHP hat es sich eingebürgert Namensräume durch Präfixe nachzubilden. Im Unserem Beispiel könnte man die eine Klasse Ilimitado_Test_PHP6 nennen, die andere Project_Test_PHP6.

class Ilimitado_Test_PHP6
{
  public static function namespace()
  {
  	echo 'Namespace Test PHP6';
  }
}
class Project_Test_PHP6
{
  public static function namespace()
  {
  	echo 'Ein ganz anderer Namespace Test für PHP6';
  }
}
Ilimitado_Test_PHP6::bar();
Project_Test_PHP6::bar();

Die Einführung von echten Namespaces in PHP6 ermöglicht nun folgenden Quellcode, wo Prefixe für Klassennamen damit zukünftig der Vergangenheit angehören sollten.

namespace Ilimitado
class Test_PHP6
{
  public static function namespace()
  {
  	echo 'Namespace Test PHP6';
  }
}
// Alles was bis hier als Klassen (oder Variablen) definiert wurde gehört dem Namespace Ilimitado an
 
namespace Project
class Test_PHP6
{
  public static function namespace()
  {
  	echo 'Ein ganz anderer Namespace Test für PHP6';
  }
}
// Alles was bis hier als Klassen (oder Variablen) definiert wurde gehört dem Namespace Project an
 
Ilimitado::Test_PHP6::namespace();
Project::Test_PHP6::namespace();
//Auch möglich, da noch der Project Namespace gilt...
Test_PHP6::namespace();

Der Aufruf einer Klasse oder Variable aus einem PHP Namespace wird also mit dem bereits bekannten Gültigkeitsbereichsoperator (::) stattfinden

Namespace oder Klassennamen können im globals space (also nicht in Klassen oder Funktionen) auch importiert werden:

require 'Ilimitado/Test/Php6.php';
import Ilimitado;
import Ilimitado::Test_PHP6; as iSpace;
 
$x = new Ilimitado::Test:PHP6();
$y = new Test_PHP6();
$z = new iSpace();
Test_PHP6::namespace();

Des weiteren existiert ein leerer Namensraum, um Klassen aus dem global scope, welche keinem Namensraum zugehören aufzurufen

//kein Namespace
class Test_PHP6
{
  public static function namespace()
  {
  	echo 'Namespace Test PHP6';
  }
}
 
namespace Project
class Test_PHP6
{
  public static function namespace()
  {
  	echo 'Ein ganz anderer Namespace Test für PHP6';
  }
}
// Alles was bis hier als Klassen (oder Variablen) definiert wurde gehört dem Namespace Project an
 
Test_PHP6::namespace();           //gibt aus 'Ein ganz anderer Namespace Test für PHP6', da noch der namespace project gilt
Project::Test_PHP6::namespace();  //gibt aus 'Ein ganz anderer Namespace Test für PHP6'
::Test_PHP6::namespace();         //gibt aber aus 'Namespace Test PHP6'

In welchem Namespace man sich befindet kann man über die neue Konstante __NAMESPACE__ herausfinden, in ihr steht immer der aktuelle PHP Namensraum.
Mehr über Namespaces in PHP6 gibt es bei David Coallier zum einen etwas allgemeines, dann Details zu Konstanten und noch Anmerkungen was Namespaces nicht sind.

Konsequenzen der Abschaffung von register_globals, HTTP_*_Vars, magic_quote und dem safe_mode

Die php.ini Einstellung register_globals war, wie allgemein bekannt sein dürfte, eine immense Sicherheitslücke. Immerhin wurden sämtliche über POST oder GET übergebenen Variablen als global space Variablen zur Verfügung gestellt. Was zunächst eine gewisse Bequemlichkeit brachte aber im Endeffekt auch riesen Sicherheitslöcher.
Wer zu sehr auf diese Option gesetzt hat, und in PHP6 nicht sofort alles neu programmieren möchte, der kann mit Hilfe eines kleinen Scriptes, welches zu Beginn seines bisherigen Scriptes geladen werden muss, die register_globals auch in PHP6 nachahmen.
Das dies natürlich absolut nicht empfehlenswert ist dürfte klar sein. Den Code dazu finden man in den PHP6 Sourcen in der README.UPDATING_TO_PHP6 Datei.

Ähnlich geht’s den langen Arrays der Form HTTP_*_Vars. Diese sind nicht mehr verfügbar nur noch ihre kurzen Varianten (z.B. $_GET oder $_POST). Mit folgendem Code, der README.UPDATING_TO_PHP6 Datei entnommen, kann man aber die long arrays auch in PHP6 verfügbar machen:

if (!ini_get('register_long_arrays')) {
	$HTTP_POST_VARS =& $_POST;
	$HTTP_GET_VARS =& $_GET;
	$HTTP_COOKIE_VARS =& $_COOKIE;
	$HTTP_SERVER_VARS =& $_SERVER;
	$HTTP_ENV_VARS =& $_ENV;
	$HTTP_POST_FILES =& $_FILES;
}

Das die magic_quote Option in PHP6 nicht mehr mit dabei ist, kann ich nur glutheißen, denn letztendlich konnte man bisher nie darauf vertrauen, ob sie aktiviert ist oder nicht – man konnte sich bisher also einfach nicht darauf verlassen das magic_quotes am Einsatzort nachher auch verfügbar waren. Und zu allem Überfluss ist es an manchen stellen gar nicht erwünscht diese Funktionalität immer zu haben etc.
Schlussendlich wird man sich durch die neuen Input Filter diese Funktionalität nachbauen und dann geziehlt einsetzen können bzw. einfach addslashes benutzen (z.B. natürlich auch per foreach Schleife über die Arrays $_GET, $_POST, $_COOKIE)

Der save_mode von PHP erwirkt im wesentlichen zwei Dinge. Zunächst werden einige Funktionen von PHP gesperrt. (z.B. Systembefehle auszuführen, PHP Konfiguration ändern, maximale Ausführzeit ändern…) Außerdem, PHP Scripte haben nur noch Zugriff auf Dateien, die dem gleichen User gehören, wie dem PHP Script (bzw durch setzen von safe_mode_gid der Gruppe).
Dies alles ist der Versuch Sicherheitsprobleme bei gemeinsam genutzten Servern zu lösen, welcher sich aber in der Praxis einfach nicht bewährt hat, bzw dessen Funktionalität auch anders erreicht werden kann.

Labels in break Anweisungen als Art goto-Konstrukt
Beim nennen des Stichworts goto bricht in der Regel sofort ein (Glaubens) Krieg unter Programmieren los – was aber nüchtern betrachtet unnötig ist. In PHP6 ist wohl geplant eine goto Funktionalität zu erreichen, ganz so leicht wird’s den Spaghetti Künstlern aber nicht gemacht und sparsam, vernünftig, an der richtigen Stelle eingesetzt wird’s eine wahre Bereicherung. Das Prinzip sieht dann so aus:

for($i = 0; $i < 10; $i++)
{
  if ($i === 5)
  {
    break goto_label_test;
  }
}
echo 'Dieser Satz darf nicht erscheinen, wenn in PHP6 Labels in der break Anweisung zugalssen sind.';
goto_label_test:
echo 'Test PHP6 Labels abgeschlossen'; //erwartete Ausgabe

Natürlich macht dies erstmal in komplexeren if, while oder for Schleifen richtig Sinn.

der if-set-or() Operator
Das Prinzip hier hinter ist es den Syntax für den Vorgang “Wenn Variable $foo nicht gesetzt ist (nicht initialisiert ist), dann initialisiere sie mit folgendem Wert: bar”
Dies würde man bisher folgendermaßen bewerkstelligen:

if(!isset($foo))
{
  $foo = 'default';
}
 
//oder etwas kürzer
$foo = isset($foo) ? $foo : 'default';

Der if-set-or Operator würde den oberen Code folgendermaßen angehen (sprich dies wäre äquivalent):

//wenn $foo einen Wert enthält bleibt dieser, ist $foo nicht initialisiert dann nimm den angegebenen Wert
$foo = ifsetor($foo, 'default');

Was in PHP6 kommen soll ist aber eine andere Variante, nämlich soll der ?: Operator folgendermaßen genutzt werden dürfen, was bisher ja nicht geht:

//wenn $foo einen Wert enthält bleibt dieser, ist $foo nicht initialisiert dann nimm den angegebenen Wert
$foo = isset($foo) ?: 'default';

Diese Variante bietet natürlich noch etwas mehr als nur ein einfach ifsetor() Befehl, z.B.

//wenn $foo größer als 20 ist bleibt $foo wie es ist, sonst setze $foo auf 0
$foo = ($foo > 20) ?: 0;

Die zuschaltbarern Input-Filter
Diese bereits für PHP 5.3 geplanten Features sind eine Reaktion auf XSS Hacks und sollen den Entwicklern Helfen Policys für das Filtern von Eingaben von außen ($_GET, $_POST,$_COOKIE…) für die gesammte Plattform zu erstellen.
Im aktuellen PHP6 Snapshot gibt es eine Datei Namens README.input_filter, diese Demonstriert ein wenig die wohl nötige Vorgehensweise.
Leider konnten wir aber nicht mehr darüber finden, so wie es sich annhört handelt es sich ja dabei um die bereits bekannte PECL Erweiterung input_filter

Soweit mal unsere Erkenntnisse zu PHP6, noch ist ja viel Zeit, denn mit einer Veröffentlichung von PHP6 kann man wohl frühestens Ende 2008 Anfang 2009 rechnen.
Dies belegt auch die neuste Aussage von Zend-Gründer Zeev Suraski im 2. Teil des Interviews auf golem.de wo unter anderem auch ein ganz neue rPunkt zur Sprache kam – die Entwicklung von Ajax-Tools, die ähnlich dem Google Web Toolkit eine Entwicklung von Ajax Anwendung in PHP ermöglichen und dann in Javascript umgewandelt werden sollen.
Sobald sich wieder ein größerer Schritt tut, und wir was Neues in PHP6 entdecken werden wir es natürlich sammt Beispielen hier berichten.

Hier nun noch einige andere Sammlungen und Beiträge zu PHP6
PHP6 im Weblog von Alex Kanub
Änderungen in PHP 6 auf Visualhype
Know-how: PHP 6: Alt und neu PHP 6 – ein Ausblick
Interview mit Zend-Gründer Zeev Suraski (Teil 1) auf golem.de
Interview mit Zend-Gründer Zeev Suraski (Teil 2) auf golem.de
Einführung zu PHP 6

Wenn dir dieser Beitrag gefällt, lade den Autor doch mal zu einem Drink ein ;-)

Broadcast us
  • Yigg
  • Webnews.de
  • Digg
  • MisterWong
  • del.icio.us
  • Technorati
  • DZone
  • Facebook
  • Google Bookmarks
  • Reddit
  • StumbleUpon
  • TwitThis

Tags: , , ,

2 Responses

  1. //wenn $foo einen Wert enthält bleibt dieser, ist $foo nicht initialisiert dann nimm den angegebenen Wert
    $foo = isset($foo) ?: ‘default’;

    //wenn $foo größer als 20 ist, setze $foo auf 0, sonst bleibt $foo wie es ist
    $foo = ($foo > 20) ?: 0;

    Das widerspricht sich. Ich glaube letzteres heißt eher
    Wenn $foo *nicht* größer als 20 ist, wirds auf 0 gesetzt

  2. Das stimmt natürlich, da ist uns ein Fehler unterlaufen.
    Vielen Dank für den Hinweis!

    Richtig ist:
    //wenn $foo größer als 20 ist bleibt $foo wie es ist, sonst setze $foo auf 0
    $foo = ($foo > 20) ?: 0;

Leave a Reply