Henry: global /Globale Variable funktioniert nicht wie erhofft

problematische Seite

Hallo,

vielleicht trügt mich meine Erinnerung was die Nutzung betrifft, vielleicht verstehe ich auch das Manual nicht, vielleicht wurde global $xy auch abgeschafft ohne dass dies im Manual steht.

Hatte das so in Erinnerung, eine Variable deklariert mit dem Vorwort global, sollte die Variable auch ausserhalb der Funktion verfügbar machen. Nun passieren aber kuriose Dinge.


function tuwas()
{
$a = 123;
$GLOBALS['g'] = $a;
}

tuwas();
$out = $GLOBALS['g'];
echo "<h1>Ausgabe: $out</h1>"; 

Das ist soweit OK wie erwartet.

function tuwas()
{
$a = 123;
global $a;

}

tuwas();
echo "<h1>Ausgabe: $a</h1>";

Hier tut sich gar nichts, auch keine Fehlermeldung, Wert bleibt leer.

function tuwas()
{
$a = 123;
global $a;
$GLOBALS['g'] = $a;
}

tuwas();
$out = $GLOBALS['g'];
echo "<h1>Ausgabe: $out $a</h1>";

Nun mal gemischt. Da funktioniert nicht mal mehr $out. Warum? Wahrscheinlich nur ne unsinnige Kleinigkeit, aber dann übersehe ich die im Moment.

Gruss
Henry

--
Meine Meinung zu DSGVO & Co:
„Principiis obsta. Sero medicina parata, cum mala per longas convaluere moras.“

akzeptierte Antworten

  1. problematische Seite

    Hello Henry,

    function tuwas()
    {
    $a = 123;
    global $a;
    
    }
    
    tuwas();
    echo "<h1>Ausgabe: $a</h1>";
    

    Hier tut sich gar nichts, auch keine Fehlermeldung, Wert bleibt leer.

    Du legst in der Funktion eine Varible $a implizit an durch Zuweisung.
    Dann holst Du die Variable $a aus dem globalen Scope und redefinierst sie lokal.

    Da die Variable im globalen Skope vorher nicht vorhanden war, wurde sie dort mit NULL oder false angelegt. Im lokalen Skope wurde $a redefiniert durch die global-Anweisung.

    Ändere die Reihenfolge.
    Benutze var_dump() zum Debuggen

    Glück Auf
    Tom vom Berg

    --
    Es gibt nichts Gutes, außer man tut es!
    Das Leben selbst ist der Sinn.
    1. problematische Seite

      Hallo TS,

      Ändere die Reihenfolge.

      Stimmt. Jetzt erinnere ich mich auch wieder ein wenig daran. Durch global wird die Var auch gesetzt. Intuitiv meinte ich es wird lediglich eine vorhandene var als global deklariert.

      Danke dir.

      Benutze var_dump() zum Debuggen

      Nutze ich meistens. Kam aber hier nur NULL raus, half mir daher nicht weiter.

      Gruss
      Henry

      --
      Meine Meinung zu DSGVO & Co:
      „Principiis obsta. Sero medicina parata, cum mala per longas convaluere moras.“
  2. problematische Seite

    Hallo Henry,

    du kennst die PHP-Dokumentation über den Geltungsbereich von Variablen?

    Viele Grüße
    Robert

    1. problematische Seite

      Hallo Robert,

      du kennst die PHP-Dokumentation über den Geltungsbereich von Variablen?

      ähm... Ja, habs sogar selbst verlinkt. Daher bin ich jetzt nicht sicher, was du damit sagen möchtest?

      Gruss
      Henry

      --
      Meine Meinung zu DSGVO & Co:
      „Principiis obsta. Sero medicina parata, cum mala per longas convaluere moras.“
      1. problematische Seite

        Hallo Henry,

        da wird es doch genau erklärt:

        Zunächst ein Beispiel für die Verwendung von global:

        <?php
        $a = 1;
        $b = 2;
        
        function Sum()
        {
           global $a, $b;
        
           $b = $a + $b;
        } 
        
        Sum();
        echo $b;
        ?>
        

        Das obige Skript gibt 3 aus. Durch das Deklararieren der Variablen $a und $binnerhalb der Funktion als global, weisen alle Referenzen zu beiden Variablen auf die nun globalen Werte.

        Viele Grüße
        Robert

        1. problematische Seite

          Hello,

          da steht aber nichts davon, wann die Global-Deklaration stattfinden muss. Bei Funktionen ist es schließlich auch egal, ob man sie vor oder nach ihrer ersten Benutzung im Quellcode niederlegen muss.

          Da lob ich mir mal wieder die strengen Compilersprachen, wid z. B. (Turbo-)Pascal.

          Glück Auf
          Tom vom Berg

          --
          Es gibt nichts Gutes, außer man tut es!
          Das Leben selbst ist der Sinn.
          1. problematische Seite

            Hallo

            da steht aber nichts davon, wann die Global-Deklamation stattfinden muss. Bei Fhnktionen ist es schließlich auch egal, ob man sie vor oder nach ihrer ersten Benutzung im Quellcode niederlegen muss.

            Entschuldige, aber das ist meiner Meinung nach selbsterklärend. Wenn ich die Variablen aus dem globalen Scope mit global in die Funktion hole (anstatt sie als Parameter zu übergeben), muss ich das natürlich tun, bevor ich sie innerhalb der Funktion benutzen möchte. Sonst existieren sie schlicht nicht beziehungsweise es wird innerhalb der Funtkion eine andere, gleichnamige Variable angelegt, die mit der Variable außerhalb der Funktion nichts weiter als ihren Namen gemein hat. Alles andere ergibt absolut keinen Sinn und muss daher (eigentlich) nicht erklärt werden.

            Tschö, Auge

            --
            Ein echtes Alchimistenlabor musste voll mit Glasgefäßen sein, die so aussahen, als wären sie beim öffentlichen Schluckaufwettbewerb der Glasbläsergilde entstanden.
            Hohle Köpfe von Terry Pratchett
            1. problematische Seite

              n'Ahmd,

              da steht aber nichts davon, wann die Global-Deklamation stattfinden muss. Bei Fhnktionen ist es schließlich auch egal, ob man sie vor oder nach ihrer ersten Benutzung im Quellcode niederlegen muss.

              Entschuldige, aber das ist meiner Meinung nach selbsterklärend.

              nein, so einfach ist es eben nicht. Es gibt in vielen Programmiersprachen Fälle, in denen die Definition oder sogar die Deklaration nicht unbedingt vor der ersten Verwendung erfolgen muss. Auch in PHP kann ich z.B. Funktionen aufrufen, die erst weiter unten im Quelltext definiert sind (in C bräuchte man dafür zumindest eine Vorab-Deklaration, besser noch einen Prototypen). Also warum sollte das nicht mit globals-Deklarationen ebenso funktionieren?
              Die Annahme ist zumindest legitim, denn auch PHP ist ja keine reine Scriptsprache mehr, die den Quellcode streng sequentiell interpretiert - vielmehr werden auch PHP-Quelldateien "on the fly" compiliert. Warum der Compiler bei Funktionen vorausschauen kann, bei globals aber nicht, ist nicht wirklich logisch erklärbar.

              Wenn ich die Variablen aus dem globalen Scope mit global in die Funktion hole (anstatt sie als Parameter zu übergeben), muss ich das natürlich tun, bevor ich sie innerhalb der Funktion benutzen möchte.

              Wenn der Code streng sequentiell Zeile für Zeile interpretiert würde, könnte ich dem Argument folgen. So ist es aber nur ein suboptimal gelöstes Detail der Implementierung.

              Ciao,
               Martin

              --
              Computer müssen weiblich sein: Eigensinnig, schwer zu durchschauen, immer für Überraschungen gut - aber man möchte sie nicht missen.
              1. problematische Seite

                Hallo

                Wenn ich die Variablen aus dem globalen Scope mit global in die Funktion hole (anstatt sie als Parameter zu übergeben), muss ich das natürlich tun, bevor ich sie innerhalb der Funktion benutzen möchte.

                Wenn der Code streng sequentiell Zeile für Zeile interpretiert würde, könnte ich dem Argument folgen. So ist es aber nur ein suboptimal gelöstes Detail der Implementierung.

                Auch wenn PHP mittlerweile mehr kann, es ist nunmal als prozedurale Sprache gestartet und global ist nun einmal ein Erbe aus genau dieser Zeit.

                Tschö, Auge

                --
                Ein echtes Alchimistenlabor musste voll mit Glasgefäßen sein, die so aussahen, als wären sie beim öffentlichen Schluckaufwettbewerb der Glasbläsergilde entstanden.
                Hohle Köpfe von Terry Pratchett
            2. problematische Seite

              Hallo Auge,

              Entschuldige, aber das ist meiner Meinung nach selbsterklärend.

              Meiner Meinung nach aber nicht, erst wenn man es weiß. Intuitiv würde ich denken (so habe ich ja auch gedacht) ich erstelle eine Variable und im nächsten Zug deklariere ich diese als globale Variable. Dass PHP dann aber den vorherigen Wert löscht, anstatt zu wissen, ah die Variable existert bereits, also nehmen wir die und machen die global, hatte ich nicht vermutet, bzw. vergessen. Daher gehört dieser wichtige Punkt m.M.n. ins Manual. Die sind ja auch sonst bemerkenswert gut darin auf Fallstricke hinzuweisen, und das hier ist einer.

              Gruss
              Henry

              --
              Meine Meinung zu DSGVO & Co:
              „Principiis obsta. Sero medicina parata, cum mala per longas convaluere moras.“
              1. problematische Seite

                Hallo,

                Intuitiv würde ich denken (so habe ich ja auch gedacht) ich erstelle eine Variable und im nächsten Zug deklariere ich diese als globale Variable.

                das wäre genau der umgekehrte Weg: Du deklarierst erst eine ganz gewöhnliche lokale Variable in der Funktion, und erklärst sie dann für global.

                Dass PHP dann aber den vorherigen Wert löscht, anstatt zu wissen, ah die Variable existert bereits, also nehmen wir die und machen die global, hatte ich nicht vermutet, bzw. vergessen.

                Naja, die Herangehensweise von PHP ist eben eine andere. Das Keyword global bedeutet: Es gibt im globalen Scope eine Variable; benutze die auch hier in der Funktion.
                Dass eine gleichnamige lokale Variable dann verdeckt wird (gelöscht wird sie nicht, du kannst sie bloß nicht mehr ansprechen), ist ein blöder Nebeneffekt.

                Ciao,
                 Martin

                --
                Computer müssen weiblich sein: Eigensinnig, schwer zu durchschauen, immer für Überraschungen gut - aber man möchte sie nicht missen.
              2. problematische Seite

                Hallo

                Entschuldige, aber das ist meiner Meinung nach selbsterklärend.

                Meiner Meinung nach aber nicht, erst wenn man es weiß. Intuitiv würde ich denken (so habe ich ja auch gedacht) ich erstelle eine Variable und im nächsten Zug deklariere ich diese als globale Variable. Dass PHP dann aber den vorherigen Wert löscht, anstatt zu wissen, ah die Variable existert bereits, also nehmen wir die und machen die global, hatte ich nicht vermutet, bzw. vergessen.

                Das ist eine absolute Falschinterpretation von global. Mit global erkläre ich nicht eine Variable aus dem eigenen Geltungsbereich/Scope für global verfügbar, sondern hole sie aus einem Geltungsbereich in einen anderen hinein. Typischerweise in eine Funktion, die ihren eigenen Scope hat und in dem eine nicht übergebene Variable aus dem globalen Raum schlicht nicht existiert.

                Daher gehört dieser wichtige Punkt m.M.n. ins Manual. Die sind ja auch sonst bemerkenswert gut darin auf Fallstricke hinzuweisen, und das hier ist einer.

                Meiner Meinung nach ist es keiner, aber das spielt für dich natürlich keine Rolle.

                Zudem ist das Beispiel auf der verlinkten Dokuseite eindeutig. Erst werden die Variablen $a und $b mit global in den Geltungsbereich der Funktion übernommen und erst dann werden sie für die Addition ($b = $a + $b;) benutzt. Selbsterklärend.

                Tschö, Auge

                --
                Ein echtes Alchimistenlabor musste voll mit Glasgefäßen sein, die so aussahen, als wären sie beim öffentlichen Schluckaufwettbewerb der Glasbläsergilde entstanden.
                Hohle Köpfe von Terry Pratchett
                1. problematische Seite

                  Hallo Auge,

                  Das ist eine absolute Falschinterpretation...

                  Aha, na schauen wir mal...

                  von global. Mit global erkläre ich nicht eine Variable aus dem eigenen Geltungsbereich/Scope für global verfügbar, sondern hole sie aus einem Geltungsbereich in einen anderen hinein. Typischerweise in eine Funktion, die ihren eigenen Scope hat und in dem eine nicht übergebene Variable aus dem globalen Raum schlicht nicht existiert.

                  Dann müsste es ja zumindest innerhalb der Funktion funktionieren, richtig?

                  function tuwas()
                  {
                  
                  $a = 123;
                  
                  global $a;
                  
                  echo "<h1>xxx $a xxx</h1>";
                  
                  $GLOBALS['g'] = $a;
                  }
                  
                  tuwas();
                  $out = $GLOBALS['g'];
                  echo "<h1>Ausgabe: $out $a</h1>";
                  

                  Tut es aber nicht weder innen noch außen. Bedeutet für mich klar die Variable $a wurde überschrieben mit NULL.

                  Meiner Meinung nach ist es keiner, aber das spielt für dich natürlich keine Rolle.

                  So wenig wie für dich.

                  Zudem ist das Beispiel auf der verlinkten Dokuseite eindeutig. Erst werden die Variablen $a und $b mit global in den Geltungsbereich der Funktion übernommen und erst dann werden sie für die Addition ($b = $a + $b;) benutzt. Selbsterklärend.

                  Nein, Fallstrick. 😉

                  Gruss
                  Henry

                  --
                  Meine Meinung zu DSGVO & Co:
                  „Principiis obsta. Sero medicina parata, cum mala per longas convaluere moras.“
                  1. problematische Seite

                    Hallo

                    Hallo Auge,

                    Das ist eine absolute Falschinterpretation... Aha, na schauen wir mal...

                    von global. Mit global erkläre ich nicht eine Variable aus dem eigenen Geltungsbereich/Scope für global verfügbar, sondern hole sie aus einem Geltungsbereich in einen anderen hinein. Typischerweise in eine Funktion, die ihren eigenen Scope hat und in dem eine nicht übergebene Variable aus dem globalen Raum schlicht nicht existiert.

                    Dann müsste es ja zumindest innerhalb der Funktion funktionieren, richtig?

                    Nein, nicht so, wie du es machst. Und das ist deutlich sichtbar.

                    function tuwas()
                    {
                    
                    $a = 123;
                    
                    global $a;
                    
                    echo "<h1>xxx $a xxx</h1>";
                    
                    $GLOBALS['g'] = $a;
                    }
                    
                    tuwas();
                    $out = $GLOBALS['g'];
                    echo "<h1>Ausgabe: $out $a</h1>";
                    

                    Tut es aber nicht weder innen noch außen. Bedeutet für mich klar die Variable $a wurde überschrieben mit NULL.

                    Natürlich wird sie das. Was erwartest du auch anderes?

                    Du machst in der Funktion eine Variable $a von außerhalb der Funktion global verfügbar, die es beim Aufruf der Funktion außerhalb dieser Funktion schlicht nicht gibt. Vor dem Aufruf der Funktion mit tuwas(); gibt es keine Variablendeklaration für $a. Keine Hände, keine Kekse; kein $a, keine Übernahme mit global.

                    Nochmal, das Schlüsselwort global ist nicht dazu gedacht, eine im Geltungsbereich der Funktion erstellte Variable global verfügbar zu machen, sondern eine Variable aus einem übergeordneten Geltungsbereich in die Funktion hinein zu holen (und den Wert an die der Variable im übergeordneten Geltungsbereich zu manipulieren). Du überschreibst innerhalb der Funktion einfach nur die lokale Variable $a mit einer nicht existierenden Variable.

                    Tschö, Auge

                    [edit]: Satzbau: an die versus der in „… den Wert der Variable im übergeordneten Geltungsbereich …“

                    --
                    Ein echtes Alchimistenlabor musste voll mit Glasgefäßen sein, die so aussahen, als wären sie beim öffentlichen Schluckaufwettbewerb der Glasbläsergilde entstanden.
                    Hohle Köpfe von Terry Pratchett
                    1. problematische Seite

                      Hallo Auge,

                      Nochmal, das Schlüsselwort global ist nicht dazu gedacht, eine im Geltungsbereich der Funktion erstellte Variable global verfügbar zu machen, sondern eine Variable aus einem übergeordneten Geltungsbereich in die Funktion hinein zu holen (und den Wert an die Variable im übergeordneten Geltungsbereich zu manipulieren).

                      genau so würde ich mir wünschen, dass es so im Manual steht. Vielleicht noch mit dem Zusatz. "Daher beachte die Reihenfolge innerhalb der Funktion". Dann wäre es wahrscheinlich auch für mich verständlich, wenn ich Jahre später das mal wieder vergessen habe.

                      Gruss
                      Henry

                      --
                      Meine Meinung zu DSGVO & Co:
                      „Principiis obsta. Sero medicina parata, cum mala per longas convaluere moras.“
        2. problematische Seite

          Hi,

          da wird es doch genau erklärt:

          nö.

          "Durch das Deklararieren der Variablen $a und $b innerhalb der Funktion als global, weisen alle Referenzen zu beiden Variablen auf die nun globalen Werte. "

          Ich hätte das eher so beschrieben:

          Durch die Angabe von global $a, $b; werden die globalen Variablen innerhalb der Funktion verfügbar gemacht.

          cu,
          Andreas a/k/a MudGuard

          1. problematische Seite

            Hello,

            Hi,

            da wird es doch genau erklärt:

            nö.

            "Durch das Deklararieren der Variablen $a und $b innerhalb der Funktion als global, weisen alle Referenzen zu beiden Variablen auf die nun globalen Werte. "

            Ich hätte das eher so beschrieben:

            Durch die Angabe von global $a, $b; werden die globalen Variablen innerhalb der Funktion verfügbar gemacht.

            ... und ggf. vorher erstellte Variablen gleichen Namens über(schrieben|laden).

            Da es aber mWn kein "Unglobal" gibt, müsste es wohl "überschrieben" heißen.

            Wie es wirklich ist, könnte man vielleicht durch Analyse des Sourcecodes noch ermitteln. Da muss ich aber leider passen. Seit Christian Seiler das Forum verlassen hat, komme ich da nicht mehr mit :-(

            cu,
            Andreas a/k/a MudGuard

            Glück Auf
            Tom vom Berg

            --
            Es gibt nichts Gutes, außer man tut es!
            Das Leben selbst ist der Sinn.
          2. problematische Seite

            Hallo

            da wird es doch genau erklärt:

            nö.

            "Durch das Deklararieren der Variablen $a und $b innerhalb der Funktion als global, weisen alle Referenzen zu beiden Variablen auf die nun globalen Werte. "

            Ich hätte das eher so beschrieben:

            Durch die Angabe von global $a, $b; werden die globalen Variablen innerhalb der Funktion verfügbar gemacht.

            Und noch mehr. Das Codebeispiel und die folgende Erklärung sagen aus, dass das Ergebnis der Manipulation (der innerhalb der Funktion als global verfügbar gemachten Variablen) in der Funktion auch außerhalb zur Verfügung steht.

            <?php
            $a = 1;
            $b = 2;
            
            function Sum()
            {
                global $a, $b;
            
                $b = $a + $b;
            } 
            
            Sum();
            echo $b;
            ?>
            

            „Das obige Skript gibt 3 aus.“ (außerhalb der Funktion!)

            global wirkt also nicht nur innerhalb der Funktion (hole mir die Variablen von außen hierher), sondern verändert den Wert der Variablen nach Ausführung der Funktion auch außerhalb dieser.

            Davon abgesehen wäre die Übergabe der Variablen als Parameter und die Verwendung eines Rückgabewerts meiner Meinung nach die meist zu bevorzugende Variante.

            <?php
            $a = 1;
            $b = 2;
            
            function Sum($a, $b)
            {
                /**
                 * Die Variablen können innerhalb der Funtion
                 * auch anders benannt sein, hier habe ich sie
                 * die Namen wegen copy'n'paste nicht verändert
                 */
                $b = $a + $b;
                return $b;
            } 
            
            $b = Sum($a, $b);
            echo $b;
            ?>
            

            Tschö, Auge

            --
            Ein echtes Alchimistenlabor musste voll mit Glasgefäßen sein, die so aussahen, als wären sie beim öffentlichen Schluckaufwettbewerb der Glasbläsergilde entstanden.
            Hohle Köpfe von Terry Pratchett