Sessie-variabelen in Drupal

Door Bèr (11 februari 2010)
Drupal kent heel nette sessie-afhandeling waar je als ontwikkelaar handig gebruik van kunt maken. Met sessie-variabelen kun je tijdelijke waardes bij één gebruiker opslaan; welke PHP over meerdere requests beschikbaar heeft. Drupal core gebruikt sessie-variabelen bijvoorbeeld om met drupal_set_message() een tekst klaar te zetten, die de eerstvolgende keer dat deze gebruiker een pagina opvraagt, bovenaan afgedrukt wordt. Jij kunt dit heel handig gebruiken, om tijdelijk waardes op te slaan, wanneer de gebruiker bijvoorbeeld een vinkje aanvinkte om grotere tekst te zien, of om een uniek bestelnummer te bewaren voor als de bezoeker uit een externe betalingsprocedure weer terugkomt op jou site. De reden van sessie-variabelen is het gegeven dat HTTP stateless is. Al je PHP-variabelen ben je kwijt, zogauw iemand een pagina ingeladen heeft. Dan wordt immers de verbinding verbroken en sluiten de webserver en PHP alles af, inclusief alle variabelen die je zette. Maar grote kans dat je gebruiker nog helemaal niet klaar is. Dat deze nog door gaat klikken, een volgend formulier wil invullen of gewoon ingelogd wil blijven. Wanneer een bezoeker een pagina opvraagt, kun je bij PHP een sessie-id opvragen, dit is een uniek nummer. Het unieke nummer wordt in de browser van de gebruiker bewaard en op aanvraag getoond aan de webserver: aan Drupal dus. Het nummer komt echter te vervallen op het moment dat de bezoeker zijn browser afsluit (de sessie beëindigt). Om dat nummer toch te bewaren kun je een session-cookie zetten, hierdoor slaat de browser van de gebruiker het sessie-id op op de harde schijf van de gebruiker. Een sessie-variabele zetten.
<?php
$_SESSION
['pirate'] = array('hello' => 'Ahoy!');
?>
Let op: zet nooit $SESSION = 'foo', je overschrijft daarmee alle andere waarden en maakt essentiële stukken Drupal kapot. Verder is het belangrijk om altijd arrays aan de $_SESSION toe te voegen. Een $_SESSION['foo'] = 'bar' werkt simpelweg niet. Het uitlezen is ook eenvoudig:
<?php
$greeting 
$_SESSION['pirate'];
print 
$greeting['hello'];
?>
Belangrijk is ook om de variabele te verwijderen als je deze niet meer nodig hebt:
<?php
unset($_SESSION['pirate']);
?>
Voordelen van Drupal's implementatie:
  • Na inloggen gaan sessie-variabelen over van de anonieme gebruiker, naar de nu ingelogde gebruiker.
  • Sessie-variabelen zijn ook op complexe load-balanced omgevingen beschikbaar. Omdat drupal alle sessies in de database opslaat, in plaats van in een bestand, zoals PHP zelf doet.
  • session_start(), session_register(), cookies opvragen cookiedetectie en andere acties zijn allemaal niet nodig: Drupal verzorgt dit.
  • Sessie-variabelen zijn veilig voor zogenaamde race-conditions of parallelle threads. Drupal zorgt voor afhandeling van zulke collisies, dus daarover hoeft de ontwikkelaar zich niet langer te bekommeren.
Belangrijk is te onthouden dat sessies maar weinig nodig zullen zijn. Allereerst moet je nooit sessie-variabelen misbruiken om binnen één request variabelen rond te sturen. Dat is een slechte eigenschap; niet alleen omdat het gebruiken van global-variabelen een slechte eigenschap is (sessie-variabelen zijn uiteraard een van de vele global-variabelen), maar vooral omdat de sessie hier écht niet voor is bedoeld. Alleen waardes die na het eindigen van een request weer beschikbaar moeten zijn, moet je in sessie-variabelen opslaan. Verder moet je waardes die aan geregistreerde gebruikers hangen, ook beter niet in sessie-variabelen opslaan. Sessie-variabelen zijn tijdelijk: als een gebruiker bijvoorbeeld zijn cookies opruimt, ben jij alle variabelen kwijt. Wil je variabelen vast opslaan, doe dat dan in de Database, dat bewaar ik echter voor een ander artikel. En als laatste dien je nooit je geheime of kritieke variabelen in een sessie op te slaan. Zulke zul je dus enkel lokaal moeten beheren en al dan niet in de database moeten opslaan. Overigens slaat Drupal de variabelen enkel op de server, in de database, op. Nooit in een cookie aan de gebruikerszijde. De gebruiker kan dus niet een cookie bewerken en daarmee deze waardes aanpassen; het cookie van de gebruiker bevat enkel een willekeurig ID. De voorbeelden waarbij sessions helemaal fout ingezet worden zijn legio. Meestal gaat het fout als je met verschillende tabs of vensters gelijktijdig één site bezoekt. In een oude versie van het veelgebruikte webhost-systeem Plesk, hadden de ontwikkelaars geen rekening gehouden met de mogelijkheid dat een site in verschillende tabs geopend kon zijn. In de ene tab was je bijvoorbeeld bezig met het beheren van 'example.com' in de andere met 'voorbeeld.nl'. Plesk hield echter met sessie-variabelen bij welke site je beheerde. Waardoor het gedrag heel onvoorspelbaar werd. Zo werkte ik aan example.com (mailadressen toevoegen) en moest ook nog example-test.nl verwijderen. Ik deed dat in verschillende tabs. De example-test.nl interface toonde me keurig een waarschuwing: 'weet u zeker dat u example-test.nl' wilt verwijderen. Maar tijdens het verwijderen keek Plesk schijnbaar naar de sessie-variabele 'actieve-site' die example.nl bevatte omdat ik daar ook op rondklikte. Plesk gooide example.com weg. Inclusief alle online back-ups, mailboxen, databases enzovoort. Eerst had Plesk dit opgelost door op een tweede venster of tab de melding te zetten 'u mag Plesk maar in één venster actief hebben'. Huidige versies hebben dit probleem niet meer. Maar bijvoorbeeld Postbank-onlinebankieren kent nog altijd veel problemen, omdat daar sessievariabelen gebruikt worden waar ze nooit voor bedoeld zijn en dus nooit voor ingezet hadden mogen worden. Een ongeschreven regel is je sessie-variabelen de naam van je module mee te geven. Dus bijvoorbeeld de piraat-module zet:
<?php
$_SESSION
['piraat_messages'] = array('Harrrr!');
?>
En niet
<?php
$_SESSION
['messages'] = array('Harrrr!');
?>
Die laatste is namelijk te generiek en dus mogelijk al in gebruik. De code is terug te vinden in session.inc.
Drupalversie:  Drupal 5 Drupal 6

Reactie toevoegen