PHP5 – dynamische Variable – superglobale Arrays

Gestern bin ich an einem kleinen aber interessanten Problem in der PHP-Programmierung hängen geblieben. Manchmal gibt es Situationen, in denen man mit einer dynamisch erzeugten Variablen – also einer Variablen, deren Bezeichnung erst zur Laufzeit festgelegt wird – eine Aufgabe schnell in den Griff bekommt. In meinem Fall versuchte ich, in einem Objekt eine dynamische Variable zu verwenden, die sich situationsbedingt entweder auf das _GET oder das _POST – Array beziehen sollte. Dies misslang zunächst – das Thema ist daher vielleicht auch für andere interessant. Es geht also um die Kombination von dynamischen Variablen mit superglobalen Arrays. Der Reihe nach:

Voraussetzung – Erzeugung von dynamischen Variablen

Einfache dynamische Variable
erzeugt man über folgenden Mechanismus

$dyn = “anracon”;
$$dyn = “anracona”;
echo ” \$dyn hat den Wert: ” . $dyn . “<br>”;
echo ” \$anracon hat den Wert: ” . $anracon . ” ( = identisch mit \$\$dyn : ” . $$dyn . ” ) <br>”;

Dynamische Array-Variable
sind etwas anders zu behandeln. Man beachte die geschweiften Klammern:

$dyna = “ay_anracon”;
${$dyna}[0] = “anracona”;
echo “\$dyna hat den Wert: ” . $dyna . “<br>”;
echo “\$ay_anracon[0] hat den Wert: ” . $ay_anracon[0] . ” ( = identisch mit \${\$dyna}[0] : ” . ${$dyna}[0] . ” ) <br>”;

(Das Ganze geht natürlich auch mit assoziativen Arrays).

Hinweis: Man könnte bei der Erzeugung dynamischer Variable zur Not auch mit der “eval”-Funktion arbeiten – das ist aber wirklich umständlich, total unsicher und wir lassen das der Übersichtlichkeit halber einfach weg.

Dynamische Bezugnahme auf “Superglobale Arrays”

Man übergibt einem Programm die GET-Variable “snr” – Bsp.: get_parameter.php5?snr=100

Enthält das Programm auf oberster Ebene (also nicht in einer Subfunktion oder einer Methode eines Objekts) folgenden Code:

$b = true;
$ind = ‘snr’;
echo ” get_parameter = ” . $_GET[$ind] . “<br>”;
if($b) { $sgv = “_GET”; }
else { $sgv = “_POST”; }
echo ” get_parameter = ” . ${$sgv}[$ind] .”<br>” ;

so erhält man zwei identische Outputzeilen mit dem Inhalt “getparameter = 100”. Die Bezugnahme der dynamischen Array-Variablen ${$sgv} auf das “_GET”-Array funktioniert also wie erwartet.

Bezugnahme auf “Superglobale Arrays” in Objektmethoden

Hat man im Programm eine Klasse und ein zugehöriges Objekt definiert, so kann man mit einer Objektmethode direkt auf das GET-Array zugreifen, da es superglobal ist und sein Geltungsbereich daher nicht mit dem “global”-Statement spezifiziert werden muss. Folgendes funktioniert also innerhalb des Programms “get_parameter.php5”:

class GetParam
{
var $gp;
function __construct()
{
$this->gp = $_GET[‘snr’];
}
}
$Ob = new GetParam;
echo ” get_parameter = ” . $Ob->gp . “<br>”;

Dynamische Bezugnahme auf “Superglobale Arrays” in Objektmethoden

Folgendes geht jedoch nicht – trotz superglobaler Gültigkeit des “_GET”-Arrays:

class GetPar
{
var $gp;
function __construct()
{
$b = true; // Nur als Beispiel
if($b) { $sgv = “_GET”; }
else { $sgv = “_POST”; }
$this->gp = ${$sgv}[‘snr’];
}
}
$Obj = new GetPar;
echo ” get_parameter = ” . $Obj->gp . “<br>”;

Denkt man etwas darüber nach, so kommt man auf folgende Vermutung: Woher soll der Interpreter wissen, dass er eine globale Variable vorsehen muss? Er wird sich schon aus Sicherheitsgründen vielmehr auf einen lokalen Gültigkeitsbereich der dynamischen Variablen zurückziehen. Dann sollte aber Folgendes helfen:

class GetP
{
var $gp;
function __construct()
{
$b = true; // Nur als Beispiel
if($b) { $sgv = “_GET”; }
else { $sgv = “_POST”; }
//
global ${$sgv};
//
$this->gp = ${$sgv}[‘snr’];
}
}
$GP = new GetP;
echo ” get_parameter = ” . $GP->gp . “<br>”;

Tatsächlich erhält man nun den gewünschten Output. Das “global”-Statement ist zwar wirklich nicht schön. Aber bei einer Bezugnahme auf ein superglobales Array kann man diese stilistische Unsauberkeit vielleicht verzeihen.

Abschließende Anmerkung

Ziel dieses Beitrags war es, darauf hinzuweisen, dass man innerhalb von Objektmethoden mit Hilfe dynamischer Variablen nicht ohne weiteres auf superglobale Arrays zugreifen kann. Scheut man das erforderliche “global” – Statement, so muss man seien Lösungen von vornherein anders konzipieren – was in der Regel sicher möglich ist.

(In meinem Fall wollte ich zu Prüfzwecken aus dem Objekt heraus einen direkten (!) Zugriff auf die Arrays ohne Zwischenvariablen gewährleisten und trotzdem die Wahl zwischen _GET und _POST haben.)