de.comp.lang.php.* FAQ

6.1. Welche Variablenarten gibt es in PHP und wie greife ich auf sie zu?

Antwort von Kristian Köhntopp

Konstanten

define(NAME, Wert);

definiert eine Konstante. Diese Konstante ist überall gültig, also nicht nur im globalen Namensraum, sondern auch in Klassen und in Funktionen.

Globale Variablen

Eine globale Variable definiert man implizit durch ihre Benutzung innerhalb des globalen Namensraumes, also einfach durch

$a = 10;

außerhalb jeder Klasse oder Funktion.

Superglobale automatische Variablen

PHP unterhält einige Arrays, die es automatisch mit Werten befüllt. Diese Arrays sind global, und sie sind anders als normale globale Variablen automatisch auch in allen Funktionen und in Klassen sichtbar, ohne dass sie mit der Anweisung global importiert werden müssen.

Es sind dies die Felder $_GET (Get-Parameter des Scriptes), $_POST (Post-Parameter des Scriptes), $_COOKIE (Cookie-Parameter des Scriptes), $_SERVER (Serverdefinierte Variablen, CGI-Umgebung), $_ENV (Umgebungsvariablen), $_REQUEST, $_FILES und $_SESSION sowie $GLOBALS (ohne führenden Unterstrich, alle globalen Variablen).

Variablen in Funktionen

In PHP hat jede Funktion ihren separaten Namensraum. In diesem Namensraum existieren nur diejenigen Variablen, die als Formalparameter der Funktion in die Funktion importiert worden sind oder die innerhalb der Funktion definiert worden sind. Diese Variablen haben die Lebensdauer des Funktionsaufrufes, d.h. sie verlieren beim Verlassen der Funktion ihren Wert.

Es ist möglich, in den Namensraum einer Funktion weitere Variablen hineinzuimportieren. Dies geschieht mit Hilfe der Anweisung global.

Beispiel:

function testfunc($para1) {
  global $glob1;

  $loc1 = 10;
  $glob1 = $glob1 + 1;

  return;
}

Diese Funktion hat zunächst einmal die Variablen $para1 und $loc1 als Parameter bzw. als lokale Variable definiert. Diese Variablen verlieren mit der schließenden Klammer "}" ihren Wert. Außerdem wird die Variable $glob1 in den Namensraum der Funktion importiert. Der Wert von $glob1 ist auch außerhalb von testfunc() sichtbar und $glob1 bleibt für die gesamte Lebensdauer des Programmes bestehen.

Weiterhin kann man innerhalb einer Funktion noch lokale Variablen definieren, die nur innerhalb der Funktion sichtbar sind, deren Wert jedoch nach dem Ende der Funktion erhalten bleibt und bei einem erneuten Funktionsaufruf erneut sichtbar wird. Dies erfolgt mit Hilfe der Anweisung static.

function testfunc2($para1) {
  global $glob1;
  static $stat1 = 0;

  $loc1 = 10;
  $glob1 = $glob1 + 1;
  $stat1 = $stat1 + 1;

  printf("Die Funktion testfunc2() wurde %s mal aufgerufen.\n",
    $stat1);
}

In diesem Beispiel ist die Anweisung static $stat1 dazu gekommen, die die Variable $stat1 als lokale, aber langlebige Variable in testfunc2() definiert und zur Vermeidung einer Warnung mit 0 initialisiert. Der Wert von $stat1 bleibt über einen einzelnen Funktionsaufruf erhalten. $stat1 zählt also im Beispiel oben die Anzahl der Aufrufe von testfunc2().

PHP definiert die superglobale Variable $GLOBALS[] vom Typ Array/Hash. Es handelt sich um einen Namen fuer die globale Symboltabelle des Interpreters. Der Name ist in allen Namensräumen sichtbar. Entsprechend ist das Konstrukt

function testfunc3() {
  global $glob1;

  $glob1 = $glob1 + 1;

  return;
}

gleichbedeutend mit

function testfunc3b() {
  $GLOBALS["glob1"] = $GLOBALS["glob1"] + 1;

  return;
}

Variablen in Klassen

Die dritte Sorte Namensräume, die in PHP existiert, sind Klassen und Objekte. Eine Klasse wird vereinbart mit der Anweisung

class MyClass {
  var $a;
  var $b;

  function c() {
    print("Der Wert von a ist %s\n", $this->a)
    $this->b = $this->b + 1;
    print("Der Wert von b ist %s\n", $this->b);
  }

  function MyClass() {
    $this->a = 10;
    $this->b = 0;
  }
}

Nach dieser Definition ist KEINE Variable belegt, aber es existiert ein Bauplan fuer MyClass-Variablen. MyClass ist ein Typ, so wie integer, float oder string Typen in PHP sind. Mit Hilfe der Anweisung "new" kann man sich Variablen nach diesem Bauplan erstellen lassen. "new" ist also eine Fabrik, der man einen Bauplan mitgibt und die nach diesem Plan Variablen herstellt.

$o = new MyClass;

Den Bauplan einer Variablen bezeichnet man als Klasse, hier der Klasse MyClass. Die nach diesem Plan gebaute Variable als ein Objekt der Klasse, hier also als das Objekt $o der Klasse MyClass. Manche Leute sagen zu dem Objekt $o der Klasse MyClass auch "$o ist eine Instanz der Klasse MyClass".

Nach einem Bauplan können mehrere Objekte gebaut werden, d.h. eine Klasse kann mehrere Instanzen haben.

$p = new MyClass;

Die Variablen mit den Namen "a" und "b" in einem Objekt der Klasse MyClass werden in PHP als Slots oder Instanzvariablen bezeichnet. Man spricht sie immer über den Namen des Objektes an:

$o->a = 17;
$p->a = 31;

Dadurch werden sie unterscheidbar, d.h. es ist erkennbar, ob man den Slot mit dem Namen "a" des Objektes $o oder des Objektes $p meint. Das kann man sich vorstellen wie Pfadnamen: In unterschiedlichen Verzeichnissen eines Dateisystems kann man ja auch Dateien mit demselben Namen liegen haben, aber diese Variablen unterscheiden sich im Pfadnamen.

Eine Klasse kann nicht nur Instanzvariablen definieren, sondern auch Instanzfunktionen, hier die Funktionen mit den Namen "c" und "MyClass". Sie werden genauso angesprochen wie die Instanzvariablen:

$o->c();
$p->c();
$o->MyClass();
$p->MyClass();

Manche Leute nennen die Funktionen eines Objektes auch "Methoden" und reden dann von "Instanzmethoden" statt "Instanzfunktionen". Das hat keinen praktischen Zweck und dient nur der Förderung der allgemeinen Verwirrung.

Beim Funktionsaufrufen gilt die folgende Sonderregel: Eine Funktion, die exakt denselben Namen hat wie die Klasse, in der sie enthalten ist, wird auch dann aufgerufen, wenn das Objekt von new gebaut wird. Diese Funktion kann also verwendet werden, um die Slots des Objektes mit Defaultwerten zu initialisieren:

$c = new MyClass;

Hier wird also die Funktion $c->MyClass() automatisch aufgerufen. Weil diese Funktion aufgerufen wird, während das Objekt nach dem Bauplan gebaut wird, nennt man eine solche Funktion einen Konstruktor. Ein Konstruktor könnte auch optionale Parameter erwarten und man könnte der Funktion dann beim Zusammenbau diese Parameter mitgeben:

class MyClass2 {

  ...

  function MyClass2($p1 = "") {
    if ($p1 != "") {
      $this->...
    }
  }
}

$mc1 = new MyClass2("beispielwert");
$mc2 = new MyClass2();

Wenn der Bauplan einer Variablen erstellt wird, wenn wir also die Klasse MyClass definieren, dann wissen wir noch nicht, unter welchen Namen die Slots und Instanzfunktionen des Objektes einmal angesprochen werden. Daher können wir in der Funktion nicht $o->a oder $p->c() schreiben, sondern müssen irgendetwas allgemeineres als Platzhalter notieren.

Die Pseudovariable $this steht dabei in einer Instanzfunktion als Platzhalter für den tatsächlichen Namen dieses Objektes. Innerhalb des Objektes $o steht $this->a also als Platzhalter fuer $o->a, innerhalb des Objektes $p steht $this->a jedoch als Platzhalter fuer $p->a. Man kann $this auch als "meine" lesen, also ist $this->a "mein Slot a" und $this->c() "meine Instanzfunktion c".

Referenzen in PHP

In PHP ist es so, dass jede Zuweisung eine Kopie der angesprochenen Variablen erzeugt:

$a = 10;
$b = 20;
$c = 30;

$arr = array( $a, $b, $c );

$arr[1] = 22;

Dies verändert den Wert von $arr[1] auf 22, aber der Wert von $b ändert sich nicht. Dies gilt auch bei Funktionsaufrufen:

function m($p1) {
  $p1 = 22;
}

m($b);

Dies setzt den Wert von $p1 auf 22, aber $p1 ist eine Kopie von $b und $b verändert den Wert nicht. Da beim Aufrufen ("Call") einer Funktion der Wert von $b in $p1 kopiert, also der Wert von $b an $p1 übergeben wird, nennt man dies "Call by value".

Man könnte auch eine Funktion schreiben, die den Namen der Variablen übergeben bekommt und dann mit Hilfe dieses Namens auf die globale Variable dieses Namens zugreift:

function m2($p1) {
  $GLOBALS[$p1] = 22;
}

m2("b");

Da in diesem Fall der Name der Variablen übergeben wird und mit Hilfe dieses Namens dann die originale Variable dieses Namens verändert wird, nennt man diese Art des Funktionsaufrufes "Call by name" (obwohl bei richtigem Call by Name noch viel obskurere Dinge möglich sind)..

Schon in PHP3 ist es so, dass man eine Funktion als "Call by Reference" definieren kann. In diesem Fall wird keine Kopie des Variablenwertes übergeben, sondern der Formalparameter p1 wird zu einem alternativen Namen für den übergebenen Wert. Wieder wird der Wert der originalen globalen Variablen verändert:

function m3(&$p1) {
  $p1 = 22;
}

m3($b);

Hier ist $p1 in m3() ein alternativer Name fuer die Variable, die beim Aufruf genennt wird. In m3($b) wird die Variable $b benannt, also ist $p1 in diesem Aufruf ein alternativer Name fuer $b. Immer wenn innerhalb dieses Aufrufes von m3() $p1 verwendet wird, wird $b angesprochen.

Seit PHP4 ist es nun so, dass man Referenzen auch an anderer Stelle verwenden kann, zum Beispiel in der o.a. Arraydefinition:

$a = 10;
$b = 20;
$c = 30;

$arr = array( &$a, &$b, &$c );

$arr[1] = 22;

print $b;

Dieses Beispiel druckt den Wert 22. In diesem Beispiel sind $arr[0], $arr[1] und $arr[2] keine Kopien der Werte von $a, $b und $c, sondern die $arr-Variablen werden zu alternativen Namen fuer $a, $b und $c. Jeder Zugriff auf $arr[1] spricht also in Wirklichkeit $b an.

Man liest "$arr[1] = &$b" als "$arr von Eins ist eine Referenz auf $b".

Klassenfunktionen in PHP4

Wenn man eine Klasse definiert, kann man in PHP3 mit dieser Klasse nichts anderes machen als mit Hilfe von "new" Objekte dieser Klasse zu erzeugen.

In PHP4 kann man jedoch nicht nur Funktionen eines Objektes aufrufen, sondern auch schon Funktionen einer Klasse. Das sind also nichts anderes als gewöhnliche Funktionsaufrufe, nur dass die Funktionsnamen sehr seltsam aussehen:

class MyClass3 {
  function c() {
    print "Ich bin Funktion c() in der Klasse MyClass\n";
  }
}

MyClass3::c();

Dieses Stück Code haette man so auch schreiben koennen und es wäre leichter zu verstehen gewesen:

function c() {
  print "Ich bin die stinknormale Funktion c()\n";
}

c();

Man kann dies verwenden, um in abgeleiteten Klassen Funktionen gleichen Namens in Oberklassen aufzurufen.

Valid HTML 4.01! Valid CSS!

6.1. Welche Variablenarten gibt es in PHP und wie greife ich auf sie zu?
http://www.php-faq.de/q/q-php-variablen.html
Archiv der de.comp.lang.php-FAQ Dies ist eine Archivseite von 2008 und wurde seitdem nicht geändert. Das dclp-FAQ-Team