Klaus Mock: Variablenverwaltungsverhalten von Perl/CGI

Beitrag lesen

Hallo,

Fangen wir mal anders an. Was passiert, wenn Anfragen von zwei Benutzern quasi gleichzeitig zum Webserver geschickt werden? Im Normalfall wird das Script zwei mal gestartet, von zwei unterschiedlichen Instanzen des Webservers aus.
Somit ist eins mal sicher, solange das Script läuft sind die Daten der beiden Benutzer von einander unabhängig.
Wenn das Script beendet ist sind auch alle Daten wieder vergessen. Was wiederum auch bedeutet, daß bei jedem Aufruf die Daten dieses Benutzers wieder hergestellt werden müssen.

Schwieriger ist es bei Systemen, welche beispielsweise mod_perl verwenden.
Hier wird das Script nur einmal pro Serverinstanz gestartet und dann nicht mehr beendet. Das heißt, daß das Script bei einer bestimmten Instanz seine globalen Variablen nicht mehr 'vergisst'.
Wenn man das und den Umstand, daß die Instanzen im Rotationsprinzip die Anfragen der Benutzer zugeordnet bekommen, berücksichtigt, ergeben sich mit globalen Variablen ein wirkliches Problem.
Es kann dadurch nämlich passieren, daß ein Benutzer plötzlich mit den Daten eines andern Benutzers arbeitet.
Um dies zu verhindern wird empfohlen, ständig 'my' zu verwenden.
Wie das ganze funktioniert, kannst du ja der Perldokumentation entnehmen (oder einem schlauen Perlbuch), bzw. hat ja im wesentloichen Bernhard schon erklärt.

Für das Problem mit den Benutzerdaten könntest Du Dir auch die Geschichte mit Objekten in Perl ansehen. Dies ist m.E. ein recht effizienter Weg, um Daten während der Laufzeit zu sammeln und an verschiedenen Stellen im Script zu verwenden.

Beispiel:

<code_of_main>
#!perl

use lib '/pfad/zu/meinen/moduln';
use Mymodule;

my $app_object = new Mymodule;

$app_object->run();

</code_of_main>

<code_of_mymodule.pm>
#!perl
package Mymodule;
use strict;
use CGI;
use Was::auch::immer;

sub new
{
my($class) = shift;
my(%params) = @_;
my($self) = {};
bless $self,$class;

$self->{CGI} = $query; #als verbindung zum CGI;
$self->init();
return $self;
}

sub init  #dient zum bestimmen der Benutzerdaten aufgrund einer SessionID;
{
my $self = shift;
#hier nur als Beispiel
$self->{SESSION_ID} = $self->{CGI}->param('SESSIONID'); #oder was auch immer

hier kaeme dann der Rest der Initialisierung hin, wie zB. Sicherheitscheck usw.

}

hier nur noch einige Beispiele, nix vollständiges

sub run
{
my $self = shift;
return $self->main() unless $self->{SESSION_ID};
return $self->error('Du sicher nicht') unless $self->{IS_ALLOWED};

}

sub error
{
my $self = shift;
my $errortext = shift;
$self->_printHeader();
print <<EOT;
$errortext
EOT
exit;
}

sub _printHeader
{
my($self) = shift;

if ($self->{CGI} && !($self->{IS_HEADER}))
 {
 print $self->{CGI}->header();
 print $self->{CGI}->start_html( -title => 'Ultimaives Webangebot');
 $self->{IS_HEADER} = 1;
 }

}

1;

</code_of_mymodule.pm>

Der Sinn der Sache ist eigentlich dieses ominöse '$self'. Da sämtliche Funktionen als Funktionen des Objekts aufgerufen werden, bekommen sie als ersten Parameter eine Referenz auf das Objekt. Über diese Referenz sind alle im Objekt gespeicherten Daten in der Funktion verfügbar. Auch Zustände, wie der, ob der HTTP-Header schon ausgegeben ist oder nicht, sind dadurch einfach zu behandeln.

Ich hoffe, halbwegs Deine Fragen beantwortet zu haben, ohne allzu langatmig zu sein

Grüße
  Klaus