dedlfix: Referenzrückgabe unter PHP 4.4.0

echo $begrüßung;

Nachdem ich neulich auf die Version 4.4.0 upgedatet habe, beschwert sich PHP nun über das halbe PEAR. Wie ich finde, macht es das teilweise zu Recht, teilweise aber nicht. Es geht dabei immer um Rückgaben von Funktionen per Referenz:

function & foo() {...}

Die Fehlermeldung lautet immer
  Notice: Only variable references should be returned by reference

Das tritt neuerdings (unter 4.3.11 kam die Notice noch nicht) auf beispielsweise in PEAR-File_Find::maptree

function &maptree(...) {  
  ...  
  return array(wert1, wert2);  
}

Hier wird ja auch keine Variablenreferenz zurückgegeben. Ich glaubte bisher, dass für das Array Speicher allokiert würde und eine Referenz darauf von der Funktion zurückgegeben wird. Und ohne & würde Speicher reserviert werden, dann eine Kopie davon zurückgegeben werden; also doppelter Speicherverbrauch plus Kopiervorgang.

Weiteres Beispiel, gleiche Klasse:

function &search(...) {  
  ...  
  return ($matches);  
}

Kaum nimmt man die überflüssigen Klammern um $matches weg, verschwindet auch die Notice. Die Klammern scheinen mir hier eine (ungewollte) Kopie zu erzeugen, die (bzw. eine Referenz darauf) statt der Referenz auf $matches zurückgegeben wird.

Noch ein Beispiel, und damit komme ich zu meiner Verwunderung:

Klasse HTML_QuickForm (verlinkt ist die ältere Version 1.155. Ab 1.156 ist die Ursache für die Warnung beseitigt/umgangen(?) )
Es geht um die Funktion createElement() (Zeile 511)
Hier das Prinzip in Kurzform:

function &x() {  
  $x = 43; // in HTML_QuickForm wird allerdings eine Objektinstanz erzeugt  
  return $x;  
}  
  
function &y() {  
  return x();  
}  
  
echo y();

Angenommen hätte ich, dass die Referenz auf $x durchgereicht wird.
In den gefixten Versionen wird die Funktion y() wie folgt definiert:

function &y() {  
  $y =& x();  
  return $y;  
}

Kann in der ersten y()-Definition nur der Compiler nicht erkennen, dass er hier von x() schon eine Referenz bekommt? Oder wodurch wird die Notice gerechtfertigt?

echo "$verabschiedung $name";

  1. Hello,

    na, hab ich denn geträumt?
    Ich habe weder mitbekommen, dass es PHP 4.3.11 gibt, noch dass es 4.4.x gibt.

    Ist das denn schon stable? Muss ich doch gleich mal lesen gehen.
    Ich dachte immer, die 4er sollte nicht weiterentwickelt werden?

    Arbeitet die neueste Version noch mit MySQL 3.23.55 zusammen?

    Harzliche Grüße vom Berg
    esst mehr http://www.harte-harzer.de

    Tom

    --
    Fortschritt entsteht nur durch die Auseinandersetzung der Kreativen
    Nur selber lernen macht schlau
    1. echo $begrüßung;

      Arbeitet die neueste Version noch mit MySQL 3.23.55 zusammen?

      Das kann ich dir nicht sagen, da ich schon lange nicht mehr "so einem alten MySQL" arbeite.

      "PHP 4.4.0 does not have any new features, and is solely a bugfix release."
      . o O ( Eine neue Notice soll kein neues Feature sein? Na ich weiß ja nicht... )

      Annehmen würde ich das trotz meiner Gedankenblase aber, dass das noch funktioniert.

      echo "$verabschiedung $name";

  2. Hallo!

    Nachdem ich neulich auf die Version 4.4.0 upgedatet habe, beschwert sich PHP nun über das halbe PEAR. Wie ich finde, macht es das teilweise zu Recht, teilweise aber nicht. Es geht dabei immer um Rückgaben von Funktionen per Referenz:

    function & foo() {...}

    Die Fehlermeldung lautet immer
      Notice: Only variable references should be returned by reference

    Das tritt neuerdings (unter 4.3.11 kam die Notice noch nicht) auf beispielsweise in PEAR-File_Find::maptree

    function &maptree(...) {

    ...
      return array(wert1, wert2);
    }

    
    >   
    > Hier wird ja auch keine Variablenreferenz zurückgegeben. Ich glaubte bisher, dass für das Array Speicher allokiert würde und eine Referenz darauf von der Funktion zurückgegeben wird. Und ohne & würde Speicher reserviert werden, dann eine Kopie davon zurückgegeben werden; also doppelter Speicherverbrauch plus Kopiervorgang.  
      
    Das ganze wurde in PHP 4.4 und 5.1 geändert, um Entwickler anzuhalten sauberer zu programmieren ;-)  
      
    Man soll eben nur Variablen von Funktionen zurückgeben, keine Ergebnisse von Ausdrücken.  
      
    Aus den [Release-Notes von PHP 4.4.0](http://de3.php.net/release_4_4_0.php):  
      
    
    > As part of the solution for the reference bug, you are very likely to find  
    > that your own or third-party PHP scripts, considered 'clean' code under  
    > previous versions of PHP, will now throw an E\_NOTICE when references are  
    > incorrectly used in the script. This is intended to alert developers to  
    > minor errors in their approach, and does not affect the script's  
    > performance in any other way.  
      
      
    
    > Weiteres Beispiel, gleiche Klasse:  
    >   
    > ~~~php
    
    function &search(...) {  
    
    >   ...  
    >   return ($matches);  
    > }
    
    

    Kaum nimmt man die überflüssigen Klammern um $matches weg, verschwindet auch die Notice. Die Klammern scheinen mir hier eine (ungewollte) Kopie zu erzeugen, die (bzw. eine Referenz darauf) statt der Referenz auf $matches zurückgegeben wird.

    Aus dem Manual Returning References:

    Note:  If you try to return a reference from a function with the syntax:
    return ($found_var); this will not  work as you now try to return the
    result of an expression, and not a variable, by reference. You can only
    return variables by reference from a function - nothing else.

    Noch ein Beispiel, und damit komme ich zu meiner Verwunderung:

    Klasse HTML_QuickForm (verlinkt ist die ältere Version 1.155. Ab 1.156 ist die Ursache für die Warnung beseitigt/umgangen(?) )
    Es geht um die Funktion createElement() (Zeile 511)
    Hier das Prinzip in Kurzform:

    function &x() {

    $x = 43; // in HTML_QuickForm wird allerdings eine Objektinstanz erzeugt
      return $x;
    }

    function &y() {
      return x();
    }

    echo y();

    
    >   
    > Angenommen hätte ich, dass die Referenz auf $x durchgereicht wird.  
    > In den gefixten Versionen wird die Funktion y() wie folgt definiert:  
    >   
    > ~~~php
    
    function &y() {  
    
    >   $y =& x();  
    >   return $y;  
    > }
    
    

    Kann in der ersten y()-Definition nur der Compiler nicht erkennen, dass er hier von x() schon eine Referenz bekommt? Oder wodurch wird die Notice gerechtfertigt?

    x() ist keine Variable, Punkt ;-)

    siehe auch:
    http://www.sitepoint.com/blog-post-view.php?id=285589
    http://wyome.com/index.php?ptid=10&aid=429&module=articles&func=display

    Grüße
    Andreas

    --
    SELFHTML Linkverzeichnis: http://aktuell.de.selfhtml.org/links/
    1. Hallo!

      Man soll eben nur Variablen von Funktionen zurückgeben, keine Ergebnisse von Ausdrücken.

      das sollte heißen:

      Man soll eben ALS REFERENZ nur Variablen von Funktionen zurückgeben, keine Ergebnisse von Ausdrücken

      Grüße
      Andreas

      --
      SELFHTML Linkverzeichnis: http://aktuell.de.selfhtml.org/links/
    2. echo $begrüßung;

      Aus den Release-Notes von PHP 4.4.0:
      Aus dem Manual Returning References:

      Wer liest denn schon Handbücher? :-)
      Die PEAR-Autoren scheinen also auch nur Menschen zu sein, die sich nicht alles merken können und gelegentlich Fehler machen...

      x() ist keine Variable, Punkt ;-)

      Nun ja, die Erklärung befriedigt mich noch nicht ganz. Ja, es ist keine Variable sondern ein Ausdruck, und ja, PHP kann (wohl) Referenzen nur auf Variablen anlegen.
      Im Grunde genommen liegt doch das Ergebnis ob als Variableninhalt oder als Ergebnis eines Ausdrucks irgendwo im Speicher, und dessen Adresse zurückzugeben sollte doch kein Problem darstellen. (Fragen des Speichermanagements lasse ich dabei mal unbeachtet.)
      Ich hätte eher was in die Richtung "Referenzen sind keine Zeiger. Mit Zeigern wäre das gegangen." als Antwort erwartet.

      Wie dem auch sei. Ich akzeptiere, dass die Warnung zu Recht kommt, merke mir die Problemfälle (so gut es geht) und bin erstmal wieder auf 4.3.11 zurückgegangen, da ich grad keine Zeit/Lust habe, PEAR-Fehler zu fixen/reporten.

      echo "$verabschiedung $name";