Kalle_B: global in verschachtelten Funktionen

Hallöle,

seit einer Stunde suche ich einen Fehler (PHP 5).

In einer Funktion habe ich ein include mit der Definition eines array und einer Funktion. In dieser inneren Funktion wird das array (vermeintlich) mit global bekannt gemacht. Es funktioniert nicht, das array ist nicht bekannt.

Kleines Beispiel- Skript:
<?PHP
$a = 1;
function x1()
{
  $b = 2;
  function x11()
  {
    global $a, $b;
    $c = 3;
    echo "a=[".$a."] b=[".$b."] c=[".$c."]<br>\n";
  }
  x11();
}
x1();
?>

Ausgabe:
a=[1] b=[] c=[3]

Wie kann ich der inneren Funktion $b bekannt machen?

LG Kalle

  1. function x1()
    {

    hier ein global $b sollte helfen

    $b = 2;
      function x11()
      {
        global $a, $b;
        $c = 3;
        echo "a=[".$a."] b=[".$b."] c=[".$c."]<br>\n";
      }

    Gruß, Samoht

    --
    fl:| br:> va:) ls:< n4:( ss:) de:] js:| mo:}
    "Computer games don't affect kids; I mean if Pac-Man affected us as kids, we'd all be running around in darkened rooms, munching magic pills and listening to repetitive electronic music."
    (Kristian Wilson, Nintendo, 1989)
    1. Hallo, Samoht,

      function x1()
      {

      hier ein global $b sollte helfen

      $b = 2;

      danke dir. So funzt das Beispiel. Eine noch unbekannte Variable als global zu deklarieren, darauf muss man erstmal kommen:

      <?PHP
      $a = 1;
      function x1()
      {
        global $b;
        $b = 2;
        function x11()
        {
          global $a, $b;
          $c = 3;
          echo "a=[".$a."] b=[".$b."] c=[".$c."]<br>\n";
        }
        x11();
      }
      x1();
      ?>

      Kalle

  2. Hallo Kalle,

    Wie kann ich der inneren Funktion $b bekannt machen?

    ich sehe keinen Grund, hier eine globale Variable zu verwenden.
    Reiche das Array von außen nach innen durch oder mache es zu einer Eigenschaft einer Klasse.

    Freundliche Grüße

    Vinzenz

    1. Hallo Vinzenz,

      Reiche das Array von außen nach innen durch

      okay, wie kann ich dann in der inneren Funktion das array verändern?

      Es ist eine uralte Funktion zum Öffnen der Datenbank, die z.B. die vergebene connect_id ins array zurückschreibt.

      Nur dass heute diese Funktion erstmalig in einer anderen Funktion verwendet wird.

      Kalle

      1. Hallo

        okay, wie kann ich dann in der inneren Funktion das array verändern?

        in PHP kannst Du auch Arrays zurückgeben.

        Es ist eine uralte Funktion zum Öffnen der Datenbank, die z.B. die vergebene connect_id ins array zurückschreibt.

        Nur dass heute diese Funktion erstmalig in einer anderen Funktion verwendet wird.

        Hmm, wenn es uralt ist, vielleicht schöner unter PHP5 objektorientiert neu schreiben :-)

        Freundliche Grüße

        Vinzenz

        1. Hallo

          Hmm, wenn es uralt ist, vielleicht schöner unter PHP5 objektorientiert neu schreiben :-)

          Nur weil etwas neuerdings (PHP 5) _möglich_ ist, stecke ich keine Arbeit hinein. Die Lebenserfahrung zeigt, dass sich das oft rächt, weil neue Probleme auftauchen. Den "Wissenszuwachs" mag kein Kunde honorieren.

          Es ist z.B. möglich, die neueste Word- Version an eine Mail zu hängen und kein Empfänger kann sie öffnen. Man könnte sagen: "Du bist nicht auf dem neuesten Stand". Das ist auch der Tischler nicht, der sein Holz mit dem Hobel bearbeitet statt mit der neuesten NC- 3D- Maschine.

          Auch, wenn ich mich jetzt oute:
          Ein Objekt ist für mich etwas, das auf äuf äußere "Reize" reagiert. Etwa in Javascript ein mit der Maus verschiebbarer <div>. Wenn Maus kommt, muss die Position verändert werden, unabhängig von anderen Objekten.

          Woher soll bei einem PHP- Script, das höchstens ein paar Minuten läuft, ein äußerer "Reiz" herkommen? Vielleicht ein anderer Benutzer, der noch schnell eine neue Anforderung nachschiebt?

          Okay, klingt konservativ. Aber würdest du eine Konserve aufmachen, nur weil du einen neuen Dosenöffner hast?

          Kalle

      2. Reiche das Array von außen nach innen durch

        okay, wie kann ich dann in der inneren Funktion das array verändern?

        über die Rückgabewerte

          
        $arr=array();  
        array_push($arr,x1());  
          
        function x1()  
        {  
          /* ... */  
          return(x11());  
        }  
          
        function x11()  
        {  
          $r=1;  
          return($r);  
        }  
          
        
        

        Ans array $arr sollte nun der Wert 1 angehängt sein.

        Meiner Ansicht nach ist das Gefährliche an globalen Variablen, dass Du ausserhalb der Funktionen nicht erkennen kannst, dass ihr Wert verändert wird.

        Gruß vom foomaker

        --
        Natürlich glaube ich an die Existenz von Ausserirdischen. Schliesslich gibt es ja auch das PERFEKTE SCRIPT.
        1. Moin!

          Reiche das Array von außen nach innen durch

          okay, wie kann ich dann in der inneren Funktion das array verändern?

          über die Rückgabewerte

          $arr=array();
          array_push($arr,x1());

          function x1()
          {
            /* ... */
            return(x11());
          }

            
          Alternativ über Referenzvariablen:  
            
          ~~~php
            
          function x13(&$var) {  
            $var[]=13; // neuen Wert dranhängen  
          }  
            
          $irgendwas = array();  
          x13($irgendwas);  
          echo $irgendwas[0]; // ergibt 13  
          
          

          Vorteil: Die Variablennamen des globalen Raumes sind flexibel und müssen nicht so lauten, wie innerhalb der Funktion.

          Außerdem kann zusätzlich auch noch ein Returnwert der Funktion entstehen.

          Nachteil: Die Funktion muß zwingend mit einer Variablen als Parameter aufgerufen werden, auf Konstanten kann man keine Referenz bilden. Außerdem ist diese Art der Werterückgabe eher ungewöhnlich und nicht schön.

          Meiner Ansicht nach ist das Gefährliche an globalen Variablen, dass Du ausserhalb der Funktionen nicht erkennen kannst, dass ihr Wert verändert wird.

          Das problematische ist, dass eine globale Variable vom Namen her festgelegt ist. Sie muß innerhalb und außerhalb der Funktion gleich heißen.

          Nun hat jeder Programmierer so seine Lieblingsvariablennamen. Wenn er jetzt zwei Funktionen schreibt, beide in separate Includes packt, und er jeweils den gleichen Variablennamen für seine globale Variable verwendet, hat er es in der Anwendung dieser Funktionen extrem schwer - vor allem, wenn die Funktionen mit den Variablen was komplett unterschiedliches machen, z.B. einmal Stringoperationen, das andere Mal Berechnung der Mehrwertsteuer.

          Allein aus diesem Grund sind globale Variablen nie nie nie zu benutzen. Der Versuch ist strafbar! Es gibt keinen rationalen Grund, es zu tun, weil es mehr als genug vernünftige Alternativen gibt.

          - Sven Rautenberg

          --
          "Love your nation - respect the others."
  3. Moin!

    Kleines Beispiel- Skript:
    <?PHP
    $a = 1;
    function x1()
    {
      $b = 2;
      function x11()
      {
        global $a, $b;
        $c = 3;
        echo "a=[".$a."] b=[".$b."] c=[".$c."]<br>\n";
      }
      x11();
    }
    x1();
    ?>

    Du kannst keine lokalen Funktionen in PHP definieren!

    Es ist ein Fehler, innerhalb einer Funktion wieder eine Funktion zu definieren. Das wird dir spätestens dann klar, wenn du die äußere Funktion ein zweites Mal aufrufst. Und wenn Funktionen nur dafür gemacht sind, ein einziges Mal aufgerufen zu werden, dann müssen es keine Funktionen sein.

    Definiere immer alle Funktionen auf globaler Ebene, nie ineinander verschachtelt!

    Ausgehend von dieser These ergibt sich für dein eigentliches Problem vermutlich eine ganz andere Lösung.

    Zumal das Verwenden von globalen Variablen auch ganz extrem böse ist.

    Warum liest du eigentlich nicht häufiger hier im Forum zu PHP-Themen mit? Das hätte dich im Laufe der Jahre schon deutlich weiter nach vorn gebracht in deinen Programmierkenntnissen, und du würdest nicht immer auf solche Advanced-n00b-Fallen auflaufen.

    - Sven Rautenberg

    --
    "Love your nation - respect the others."
    1. echo $begrüßung;

      Du kannst keine lokalen Funktionen in PHP definieren!

      Ergänzend dazu: Man kann sie zwar so verschachtelt notieren, sie werden aber nicht, wie vielleicht gedacht, angelegt. Funktionen (und Klassen) sind immer global. Sie sind auch dann noch vorhanden, wenn der Gültigkeitbereich verlassen wurde, in dem sie deklariert wurden.

      Es ist ein Fehler, innerhalb einer Funktion wieder eine Funktion zu definieren. Das wird dir spätestens dann klar, wenn du die äußere Funktion ein zweites Mal aufrufst.

      Da die Funktion ja global angelegt wurde, ist der Name bereits vergeben und ein fataler Fehler wird ausgelöst (Cannot redeclare ...).

      Definiere immer alle Funktionen auf globaler Ebene, nie ineinander verschachtelt!

      Zumindest sollte man solch offensichtliche Verschachtlungen vermeiden, weil sie Lokalität suggerieren, die jedoch nicht gegeben ist.

      Solch eine Verschachtlung ist dennoch sinnvoll, sonst hätte man sie ja gleich verbieten können. Beispiel: Gegeben sei eine Funktion, deren Aufgabe es ist, Code-Dateien nachzuladen (per include & co.). Wir befinden uns also innerhalb dieser Funktion, führen das include aus und treffen dabei auf Funktionsdefinitionen in der zu inkludierenden Datei. In den seltensten Fällen würde nun jemand ein Verhalten benötigen und erwarten, das diese Funktionen als lokale Funktionen lädt. Stattdessen landen die Funktionen aus der include-Datei im globalen Namensraum und sind von überall her aufrufbar. (__autoload() ist eine Anwendung des Prinzips, wenn es auch mit Klassen statt mit Funktionen arbeitet.)

      Warum liest du eigentlich nicht häufiger hier im Forum zu PHP-Themen mit? Das hätte dich im Laufe der Jahre schon deutlich weiter nach vorn gebracht in deinen Programmierkenntnissen, und du würdest nicht immer auf solche Advanced-n00b-Fallen auflaufen.

      Möglicherweise ist das ein Nullsummenspiel. Die Zeit, die man beim Lernen durch Mitlesen und ggf. auch Recherchieren für Probleme anderer Leute verbringt, ist man "unproduktiv". Man vermehrt zwar das eigene Wissen, lernt Verfahren und Lösungswege kennen, die man noch nicht kannte, und kann die produktiven Probleme schneller lösen oder von vornherein vermeiden. Doch das ist ein stets zu wiederholender Prozess. Die eingesparte produktive Zeit benötigt man zur Weiterbildung, wenn man am Ball bleiben will. Der vielleicht einzige Vorteil ist: die Fehler der Anderen frustrieren einen selbst nicht. Außerdem muss man sich nicht auf seine eigenen Forumsfragen sagen lassen, dass dies ein allseits beliebtes Fettnäpfchen ist, in das man sich gerade hineinprogrammiert hat.

      echo "$verabschiedung $name";