Ankündigung

Einklappen
Keine Ankündigung bisher.

4,52: Griechische Buchstaben und kleine Kapseln

Einklappen
X
  • Filter
  • Zeit
  • Anzeigen
Alles löschen
neue Beiträge

  • 4,52: Griechische Buchstaben und kleine Kapseln

    4,52:
    Mittlerweile vollkommen aus dem Fokus verschwunden, teils verteufelt, teils in den siebten Himmel gelobt, steht er da, der neuste Spross aus der PHP-Softwareschmiede: PHP 5.3. Dass PHP 5.3 mittlerweile so aus dem Mittelpunkt gerückt ist, mag zum Teil an vielen Kinderkrankheiten liegen, denn auch in der aktuellen Version PHP 5.3.3 ist es noch bei Weitem nicht ausgereift. Zum Anderen liegt es aber natürlich auch daran, dass bisher kaum ein Hoster umgesattelt hat und das wird auch sicherlich noch einige Zeit so bleiben.
    Dennoch bietet PHP 5.3 einige interessante Neuerungen, die das Programmieren einfacher und dynamischer machen können. Hierzu zählt z.B. die Unterstützung von Lambda-Funktionen (anonymen Funktionen) und Closures.

    Lambda-Funktionen sind eine äußerst praktische Sache und aus JavaScript gut bekannt. Kaum eine Sprache ist so flexibel wie JavaScript und genau das ist es, was vielen Einsteigern Kopfschmerzen bereitet und die eingefleischten JS-Spezialisten so begeistert. Konstrukte wie dieses sind in JavaScript keine Seltenheit:
    PHP-Code:
    function foobar() {
        var 
    'y';
        var 
    bla blub() {
            
    console.log(x);
            return function() {
                
    // do some more stuff
            
    };
        };
    };
    var 
    fbar foobar;
    fbar(); 
    Zugegeben, das Beispiel enthält jetzt nicht sonderlich sinnvollen Code, aber es verdeutlicht das Prinzip sehr gut: Funktionen können beliebig geschachtelt werden und lassen sich in Form von Referenzen Variablen zuweisen. So etwas war in PHP bisher in dieser Form undenkbar. Im Gegensatz zu JavaScript war PHP bisher eine sehr starre Sprache. Diese Starrheit wurde mit PHP 5.3 zumindest zu einem Teil durchbrochen, indem ebenfalls Lambda-Funktionen eingeführt wurden. An sich gehören Lambda-Funktionen zwar schon seit PHP 4.0.1 zum Sprachschatz von PHP, aber bisher waren sie nur über umständliche Konstrukte mit [MAN]create_function[/MAN]() realisierbar, was sie für den produktiven Einsatz ziemlich unattraktiv machte. Das hat sich mit PHP 5.3 aber geändert. Fortan lassen sich waschechte anonyme Funktionen bilden:
    PHP-Code:
    $func = function() {
        print 
    'Hello World!';
    };    
    // Semikolon nicht vergessen (das sind viele PHPler nicht gewohnt)!

    // Funktion ausführen
    call_user_func($func);

    // oder komfortabler:
    $func(); 
    Auch anonyme Funktionen innerhalb von anonymen Funktionen sind möglich:
    PHP-Code:
    $func = function() {
        print 
    'Hello ';
        
    $func = function() {
            print 
    'World';
        };
        
    $func();
    };
    $func(); 
    Eine solche Flexibilität auf Codebasis war in PHP bisher nur schwer zu erreichen. Sie birgt natürlich aber auch eine große Gefahr für unübersichtlichen und unwartbaren Code. Deshalb sollten anonyme Funktionen auch nur dort eingesetzt werden, wo sie auch benötigt werden, also z.B. als Callbacks.

    Das letzte Beispiel führt uns auch direkt zum nächsten Thema: den Closures. Closures sind in der Programmierung eine Kontexterhaltung. D.h., dass ein Namensraum für Variablen und Funktionen aufrecht erhalten wird, sodass eine anonyme Funktion stets auf ihn zugreifen kann. In JavaScript wird dies ständig genutzt, z.B. bei EventHandler-Callbacks:
    PHP-Code:
    var bla 'blub';
    document.getElementById('foobar').addEventListener('click', function() {
        
    console.log(bla);
    }, 
    true); 
    Obwohl die Codeausführung zum Zeitpunkt des Events schon ganz woanders ist, wird der umgebende Namensraum erhalten, sodass die Variable bla innerhalb des Callbacks immer noch gültig ist.
    In PHP 5.3 sind Closures ebenfalls möglich, allerdings wird der umgebende Kontext nicht automatisch erhalten, um die Integrität der Sprache PHP nicht vollständig zu zerstören. Da in PHP normale (nicht globale) Variablen des äußeren Kontextes in Funktionen generell nicht sichtbar sind (ein großer Unterschied zu JavaScript), wurde diese Konzeption für anonyme Funktionen beibehalten. Um dennoch Closures zu ermöglichen, wurde das Schlüsselwort use eingeführt, dem eine geklammerte kommaseparierte Liste aller Variablen folgt, die in der anonymen Funktion sichtbar sein sollen. Hier wird wie bei der Übergabe normaler Parameter zwischen Call-By-Value und Call-By-Reference unterschieden. Ersteres ist der Standard, sodass eine Änderung der Variablen innerhalb der anonymen Funktionen keinen Einfluss auf den umgebenden Kontext hat, wenn kein Referenzierungsoperator & angegeben wird.
    PHP-Code:
    $var1 'foo';
    $var2 'bar';
    $func = function() use ($var1, &$var2) {
        
    $var1 'bar';
        
    $var2 'foo';
    };
    $func();
    var_dump($var1$var2); 
    Die Ausgabe:
    Code:
    string(3) "foo"
    string(3) "foo"
    Eine weitere Sache, die man beachten sollte ist, dass in der Beta1 von PHP 5.3 die Unterstützung des $this-Kontextes in Closures entfernt wurde. Der Grund ist, dass ein Weg gefunden werden müsse, dies ohne Kompatibilitätsprobleme zu implementieren (siehe auch RFC: Removal of $this in closures).
    Folglich sind Konstrukte wie dieses zumindest vorerst nicht möglich:
    PHP-Code:
    class X
    {
        private function 
    priv() {
            print 
    'Hello World';
        }
        
        public function 
    __construct() {
            
    $test = function() use ($this) {    //Fehler!
                
    echo $this->priv();
            };
            
    $test();
        }

    Auch die direkte Benutzung von $this ohne die Benutzung von use ist nicht möglich. Es muss vorher also eine Kontextübertragung stattfinden:
    PHP-Code:
    class X
    {
        private function 
    priv() {
            print 
    'Hello World';
        }
        
        
    // Öffentliche Wrapper-Funktion, um Zugriff aus Closure zu ermöglichen
        
    public function pub() {
            return 
    $this->priv();
        }
        
        public function 
    __construct() {
            
    // Kontext übertragen
            
    $that $this;
            
    $test = function() use ($that) {
                echo 
    $that->pub();
            };
            
    $test();
        }

    Merke, dass hierdurch auch der Zugriff auf private und geschützte Member der umgebenden Klasse nicht mehr möglich ist.

    Abgesehen von diesen Einschränkungen wirkt die Implementierung aber recht solide in Anbetracht der über die Jahre gewachsenen Basis. Die PHP-Entwickler werden es nicht immer leicht haben, die Sprache PHP mit der Zeit gehen zu lassen, ohne die Abwärtskompatibilität vollständig fallen zu lassen.

    Weitere Informationen zu Lambda-Funktionen und Closures:

Lädt...
X