Unterabschnitte


Sessions

Was sind Sessions?

Mit ,,Session`` (engl.: Sitzung) bezeichnet man alle Daten, die dem Server einer Site (z.B. einem personalisierten System) während dem Verweilen eines Benutzers auf derselben bekannt sind. Verschiedene Benutzer werden somit auch durch verschiedene Sessions identifiziert.[*]

Technisch kann man sich die über einen Nutzer bekannten Daten als einen ,,serverseitigen Cookie[*]`` vorstellen. Die Daten können über einzelne Seiten hinweg benutzt und manipuliert werden, ohne dabei den Bezug zum jeweiligen Benutzer bzw. Abrufer zu verlieren. Sie werden aber - im Gegensatz zum normalen Cookie - nicht beim Client, sondern auf dem Server gespeichert. Das klingt natürlich erstmal fantastisch, da man sich so keine Gedanken über Browser-spezifische Probleme[*] machen müßte. Doch gleich die schlechte Nachricht: So einfach funktioniert das nicht, denn der Server kann bei einer normalen Anfrage nicht herausfinden, welche gespeicherte Session er dem Client zuweisen soll. Deswegen muß diese Aufgabe wiederum der Client übernehmen: Er muß eine sog. Session-ID zur Identifikation selbst speichern, was er normalerweise wieder mit Cookies macht - ein Teufelskreis.

Keine Arme, keine Kekse ...

Es gibt auch die Möglichkeit, die Session-ID per URL weiterzugeben. Es muß dabei - egal ob POST- oder GET-Anfrage - die 32-stellige ID[*]immer übergeben werden. Das passiert bei einer POST-Anfrage (Formular) über versteckte Felder[*]:
<form>
<input type="hidden"
       name="PHPSESSID"
       value="edb0e8zz5et4e9042fe0176a89cbde16" />
</form>
und bei GET über die URL:
index.php?PHPSESSID=edb0e8zz5et4e9042fe0176a89cbde16

Einen Teil dieser Arbeit kann PHP selbst übernehmen, wenn man die entsprechenden Stellen in der Konfigurationsdatei php.ini richtig eingestellt hat:

url_rewriter.tags = "a=href,area=href,frame=src,input=src,form=fakeentry"
Dies veranlaßt PHP dazu, die entsprechenden Erweiterungen bei den HTML-Tags <a>, <area>, <frame>, <input> und <form> selbst einzutragen.

Außerdem muß der Pfad, unter dem die Sessions auf dem Server gespeichert werden sollen, bei Nicht-UNIX-Systemen[*] noch angepaßt werden:

session.save_path = c:\temp\

Praxis

Datei 1 - index.php

<?php
session_start();

$string = "Test";
$integer = 1;
$array = array("Wert1", "Wert2");

session_register("string", "integer", "array");
?>
<html>
<head>
<title>Beginn</title>
</head>
<body>
<a href="index2.php">Weiter zu Index2</a>
</body>
</html>

Datei 2 - index2.php

<?php
session_start();
?>
<html>
<head>
<title>Beginn</title>
</head>
<body>
<pre>
<?php
print "String: ".$_SESSION['string']."<br />";
print "Integer: ".$_SESSION['integer']."<br />";
print "Array:<br />";
print_r($_SESSION['array']);

// In der Session gespeicherten Wert verändern
$_SESSION['integer']++;

?>
</pre>
<a href="index2.php">Erneut aufrufen</a>
</body>
</html>

Rufen wir die Datei index.php auf, so wird zuerst eine Session durch session_start gestartet. Danach füllen wir 3 Variablen mit verschiedenen Werten, die dann durch session_register [*]für die Session registriert (also gespeichert) werden. Wenn man danach über den Link die 2. Seite aufruft, bekommt man die eben gespeicherten Werte angezeigt. Wir haben in diesem Fall keinen Versuch unternommen, die Session-ID manuell weiterzugeben, sondern überlassen diese Aufgabe PHP, was nicht unbedingt vorteilhaft ist, da PHP den Browser dazu veranlaßt, die Session-ID als Cookie zu speichern und gleichzeitig teilweise die ID der URL hinzufügt. Wenn wir eine Cookie-unabhängige Seite programmieren wollen, müssen wir diese Aufgabe selbst übernehmen und an jeden Link in der HTML-Ausgabe den String ,,?SESSION-NAME=SESSION-ID`` anhängen. Der Standard-Sessionname ist PHPSESSID. Wenn wir sichergehen wollen, benutzen wir die Funktion session_name(), die den Namen als String zurückgibt[*]. Das gleiche gilt für die Session-ID, hier verwenden wir die Funktion session_id() oder alternativ die Konstante SID. Beispiel:

<?php
// Unterbinden von Cookies:
ini_set("session.use_cookies", "0");

// Da wir die Session-ID automatisch anfügen,
// muß PHP diese Aufgabe nicht mehr übernehmen:
ini_set("url_rewriter.tags", "");

...

printf('<a href="index2.php?%s=%s">Weiter ...</a>',
       session_name(),
       session_id()
      );
?>

Logout - logout.php

Irgendwann will man eine Session auch mal beenden. Das geht so:

session_unset();
session_destroy();
unset($mySessVar1, $mySessVar2, ...);
// jetzt sind die Variablen auch lokal nicht mehr definiert
header("Location: index.php?logout=true");
exit;

Aufzurufen per Link:

<a href="logout.php">Logout</a>

oder Button:

<form action="logout.php">
<input type="submit" value="Logout">
</form>

Beispiel Warenkorb

Ein gutes Beispiel für den Gebrauch von Sessions ist eine Warenkorbfunktion, wie man sie oft in Onlineshops sieht. Unser Warenkorb soll so einfach wie möglich sein:

Waren

Die Datei waren.php enthält ein Array[*] mit verfügbaren Produkten. Da diese Seite von allen anderen eingebunden wird, startet sie auch die Session und registriert die Variable warenkorb als Session-Variable.
<?php
ini_set("session.use_cookies", "0");
ini_set("url_rewriter.tags",   "");

session_start();
session_register('warenkorb');

$waren = array(
  '1' => array(
    'titel' => 'DSP Taschenbuch',
    'preis' => 9.90,
    'text' => 'Das Standardwerk zum Thema Datenbank,
               SQL und PHP als handliches Taschenbuch.'
  ),
  '2' => array(
    'titel' => 'DSP auf CD',
    'preis' => 19.90,
    'text' => 'Wenn Ihnen die Downloadzeit zu wertvoll ist,
               können sie DSP auch als CD bestellen.'
  ),
  '3' => array(
    'titel' => 'DSP Hörspiel',
    'preis' => 29.90,
    'text' => 'Das Standardwerk zum Thema Datenbank,
               SQL und PHP für Analphabeten.'
  )
);
?>
<html>
<head>
<title>Warenkorb</title>
</head>
<body>

Übersicht

Die Seite index.php soll einen Überblick über die angebotenen Produkte liefern. Weiter unten erhält man einen Überblick darüber, was man bereits bestellt hat. Über einen Entfernen-Link kann man seine bisherige Bestellung außerdem noch korrigieren.
<?php
include_once("waren.php");

foreach ($waren as $id => $produkt) {
    printf('<p>
            <b>%s</b><br />
            Preis: <b>Euro %01.2f</b><br />
            Beschreibung: <b>%s</b><br />
            <a href="bestellen.php?id=%d&%s">Bestellen</a>
            </p>',
           $produkt['titel'],
           $produkt['preis'],
           htmlentities($produkt['text']),
           $id,
           SID
          );
}

if (isset($_SESSION['warenkorb']) &&
   !empty($_SESSION['warenkorb'])) {

    print "Sie haben folgende Waren bereits ausgew&auml;hlt:";
    print "<ul>";
    foreach ($_SESSION['warenkorb'] as $id) {
        printf('<li>
                %s
                (<a href="entfernen.php?id=%d&%s">
                   Entfernen
                </a>)
                </li>',
               htmlentities($waren[$id]['titel']),
               $id,
               SID
              );
    }
    print "</ul>";
}
?>
</body>
</html>

Bestellen

Die Datei bestellen.php legt Produkte in den Warenkorb
<?php
include_once("waren.php");

if (!isset($_GET['id'])) {
    die("Kein Produkt ausgew&auml;hlt.");
}

// Wenn das Produkt noch nicht gekauft wurde...
if (!isset($_SESSION['warenkorb']) ||
    !in_array($_GET['id'], $_SESSION['warenkorb'])) {

    // In den Warenkorb legen:
    $_SESSION['warenkorb'][] = $_GET['id'];
}
?>
<p>
  Das Produkt wurde Ihrem Warenkorb hinzugef&uuml;gt.<br />
  <a href="index.php?<?php print SID; ?>">
    Zur&uuml;ck zur Startseite
  </a>
</p>
</body>
</html>

Entfernen

Mit der Seite entfernen.php kann man schließlich noch einzelne Produkte aus dem Warenkorb löschen.
<?php
include_once("waren.php");

// Wenn kein Produkt ausgewählt wurde, oder
// das Produkt nicht im Warenkorb ist...
if (!isset($_GET['id']) ||
    !in_array($_GET['id'], $_SESSION['warenkorb'])) {

  print("Sie haben dieses Produkt noch nicht bestellt,
         oder kein Produkt ausgew&auml;hlt.");
}
else {
  foreach ($_SESSION['warenkorb'] as $id => $produkt) {
    if ($produkt == $_GET['id']) {
      unset($_SESSION['warenkorb'][$id]);
    }
  }
  print "Das Produkt wurde aus Ihrem Warenkorb gel&ouml;scht.";
}
?>
<br />
<a href="index.php?<?php print SID; ?>">
  Zur&uuml;ck zur Startseite
</a>
</body>
</html>

Christoph Reeg