Session class

Gepost door Pepijn Schildkamp op 30-04-2010 20:55.

Beste,

Bij deze een classe voor in dit script lib om gebruik te maken van eigen sessies.
Deze classe is een onderdeel van een platform (MCV) waar ik mee bezig ben.
Mochten dus ook de reacties hierop goed zijn (als in, mensen kunnen het gebruiken of er iets van leren) dan zal ik het gehele platform posten.

Opbouwende kritiek is natuurlijk altijd welkom =]

Technish:
- SessionException is een classe die je er zijn bij kunt maken als je wilt, of gebruik gewoon de exception class
- De classe IpAddress is een classe die het ip address achterhaalt
Deze classes komen vanuit het framework, dus die kun je er zelf wel bijmaken.
- Classe maakt gebruik van OOP PHP 5, en PDO. Deze heb je dus ook nodig wil je het gebruiken =]

Voorbeelden
<?php
#load the Session class
Session::initialise();

#make new session var
Session::set('sKey', 'sValue');
Session::set('sKeyArray', array('Needle' => 'Value'));

#update value of existing session
Session::set('sKey', 'sNewValue');

#unset a session
Session::delete('sKey');

#get your current session id
echo Session::getId();

#destroy the whole session
Session::destroy();

#return the value type of session
Session::getType('sKey'); //returns String
Session::getType('sKeyArray'); // returns Array etc etc..
?>

Dit was het zo ongeveer wel een beetje. Maar zoals eerder aangegeven. Als er intresse is, en mijn framework is af wil ik deze wel posten. Ligt beetje aan het animo =]

Bestanden van dit script

index.php

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
<?php
/**
 * Synaps Framework
 *        An application development framework for PHP
 *
 * @authors     Pepijn Schildkamp    < pepijn@mediaflux.nl >
 *                 Joris Even            < joriseven@gmail.com >
 *
 * @copyright    
 * @link        http://www.synaps-ict.nl
 * @since        Version 0.09
 * @filesource
 *
 //------------------------------------------------------------//
 *
 * Synaps framework Session class
 *         Makes it possible to work with Synpas own Sessions for more security
 *
 * @subpackage    /Session/
 * @category    Bin
 * @author        Pepijn Schildkamp    < pepijn@mediaflux.nl >
 *
 */
 
Class Session {
    
    private static $oInstance;
    private static $_iSessionId;
    
        /**
         * __constructs
         *        Writes a new cookie with session id and safes it.
         *
         * @acces                    private
         *
         * @returns                 void
         **/

        private function __construct() {
            
            $iSessionId = $this->generateSessionId();
            
            if(!isset($_COOKIE[ 'SynapsSessionId' ])) {
                setcookie('SynapsSessionId', $iSessionId, time() + 3600);
                self::$_iSessionId = $iSessionId;
            } else {
                self::$_iSessionId = $_COOKIE[ 'SynapsSessionId' ];
                setcookie('SynapsSessionId', self::$_iSessionId, time() + 3600);
            }
        }
        
        /**
         * initialise
         *        Singleton pattern, makes sure class can be loaded once.
         *
         * @acces                    public static
         * 
         * @returns                 object
         **/
        
        public static function initialise() {
            if (is_null(self::$oInstance)) {
                $c = __CLASS__;
                self::$oInstance = new $c;
            }
            return self::$oInstance;
        }
        
        /**
         * get
         *        Returns session if exists
         *
         * @acces                    public static 
         * 
         * @returns                 value 
         **/
         
        public static function get($sKey) {
            try {
                $oGetSession = Database::pdo()->prepare('SELECT sValue, sType
                                                            FROM s_binSessions
                                                                WHERE sKey = :sKey
                                                                AND sClientSessionId = :sClientSessionId
                                                                AND sClientIpAddress = :sClientIpAddress
                                                                    LIMIT 1 ');
                    
                    $oGetSession->bindParam(':sKey', $sKey, PDO::PARAM_STR);
                    $oGetSession->bindParam(':sClientSessionId', self::$_iSessionId, PDO::PARAM_STR);
                        $sClientIpAddress = new IpAddress();
                    $oGetSession->bindParam(':sClientIpAddress', $sClientIpAddress->getIpAddress(), PDO::PARAM_STR);
                    $oGetSession->execute();
                    $rGetSession = $oGetSession->fetch(PDO::FETCH_ASSOC);
            } catch(PDOException $e) {
                throw new SessionException($e, SessionException::E_CORE_ERROR);
            }
                
            
            switch($rGetSession['sType']) {
                case 'Object':
                    return unserialize($rGetSession['sValue']);
                    break;
                
                case 'Integer':
                    return (int) $rGetSession['sValue'];
                    break;
                    
                case 'Array':
                    return unserialize($rGetSession['sValue']);
                    break;
                    
                case 'Float':
                    return (float) $rGetSession['sValue'];
                    break;
                    
                case 'String':
                    return (string) $rGetSession['sValue'];
                    break;
                    
                case 'Boolean':
                    return (bool) $rGetSession['sValue'];
                    break;
                    
                default:
                    return (string) $rGetSession['sValue'];
            }
            
        }
        
        /**
         * set
         *        sets a new value to a given session or creats a new one when nonexisting
         *
         * @acces                    static public
         *
         * @returns                 boolean
         **/
        
        public static function set($sKey, $sValue ) {
            try {
                $oCheckSession = Database::pdo()->prepare('SELECT sId
                                                            FROM s_binSessions
                                                                WHERE sKey = :sKey
                                                                AND sClientSessionId = :sClientSessionId
                                                                AND sClientIpAddress = :sClientIpAddress');
                    
                    $oCheckSession->bindParam(':sKey', $sKey, PDO::PARAM_STR);
                    $oCheckSession->bindParam(':sClientSessionId', self::$_iSessionId, PDO::PARAM_STR);
                        $sClientIpAddress = new IpAddress();
                    $oCheckSession->bindParam(':sClientIpAddress', $sClientIpAddress->getIpAddress(), PDO::PARAM_STR);
                    $oCheckSession->execute();
                    $rCheckSession = $oCheckSession->fetchAll(PDO::FETCH_ASSOC);
                    
                    $sPreparedValue = ( is_array($sValue) || is_object($sValue) ) ? serialize($sValue) : $sValue;
            } catch(PDOException $e) {
                throw new SessionException($e, SessionException::E_CORE_ERROR);
            }
            
            if(count($rCheckSession) > 0 && is_array($rCheckSession)) {
            
                try {
                    $oUpdateSession = Database::pdo()->prepare('UPDATE s_binSessions
                                                                    SET sValue = :sValue,
                                                                        sType = :sType,
                                                                        sClientDate = NOW()
                                                                        WHERE sKey = :sKey
                                                                        AND sClientSessionId = :sClientSessionId
                                                                        AND sClientIpAddress = :sClientIpAddress');
                                                                        
                        $oUpdateSession->bindParam(':sValue', $sPreparedValue, PDO::PARAM_STR); 
                        $oUpdateSession->bindParam(':sKey', $sKey, PDO::PARAM_STR); 
                        $oUpdateSession->bindParam(':sClientSessionId', self::$_iSessionId, PDO::PARAM_STR); 
                            $sClientIpAddress = new IpAddress;
                        $oUpdateSession->bindParam(':sClientIpAddress', $sClientIpAddress->getIpAddress(), PDO::PARAM_STR);
                        $oUpdateSession->bindParam(':sType', self::Type($sValue), PDO::PARAM_STR);    
                        $oUpdateSession->execute();
                } catch(PDOException $e) {
                    throw new SessionException($e, SessionException::E_CORE_ERROR);
                }
                    
            } else {
                try {
                    $oNewSession = Database::pdo()->prepare('INSERT INTO s_binSessions
                                                                        (     sClientSessionId,
                                                                            sClientIpAddress,
                                                                            sClientDate,
                                                                            sKey,
                                                                            sValue,
                                                                            sType    )
                                                                    VALUES
                                                                        (     :sClientSessionId, 
                                                                            :sClientIpAddress,
                                                                            NOW(),
                                                                            :sKey,
                                                                            :sValue,
                                                                            :sType                    ) ');
                    
                        $oNewSession->bindParam(':sClientSessionId', self::$_iSessionId, PDO::PARAM_STR);
                            $sClientIpAddress = new IpAddress();
                        $oNewSession->bindParam(':sClientIpAddress', $sClientIpAddress->getIpAddress(), PDO::PARAM_STR);
                        $oNewSession->bindParam(':sKey', $sKey, PDO::PARAM_STR);
                        $oNewSession->bindParam(':sValue', $sPreparedValue, PDO::PARAM_STR);
                        $oNewSession->bindParam(':sType', self::Type($sValue), PDO::PARAM_STR);
                        $oNewSession->execute();
                    } catch(PDOException $e) {
                        throw new SessionException($e, SessionException::E_CORE_ERROR);
                    }
            }
        }
        
        
        /**
         * delete
         *        deletes given session
         *
         * @acces                    static public
         *
         * @returns                 boolean
         **/
        
        public static function delete($sKey) {
            $oCheckSessionType = Database::pdo()->prepare('DELETE
                                                            FROM s_binSessions
                                                                WHERE sKey = :sKey
                                                                AND sClientSessionId = :sClientSessionId
                                                                AND sClientIpAddress = :sClientIpAddress');
                
                $oCheckSessionType->bindParam(':sKey', $sKey, PDO::PARAM_STR);
                $oCheckSessionType->bindParam(':sClientSessionId', self::$_iSessionId, PDO::PARAM_STR);
                    $sClientIpAddress = new IpAddress();
                $oCheckSessionType->bindParam(':sClientIpAddress', $sClientIpAddress->getIpAddress(), PDO::PARAM_STR);
                    if($oCheckSessionType->execute()) {
                        if( $oCheckSessionType->rowCount() > 0 ) {
                            return true;
                        } else {
                            throw new SessionException('Can\'t return Type of a nonexisting session', SessionException::E_CORE_ERROR);
                            return false;
                        }
                    } else {
                        throw new SessionException('Can\'t return Type of a nonexisting session', SessionException::E_CORE_ERROR);
                        return false;
                    }
        }
        
        
        /**
         * destroy
         *        Ends the session.
         *
         * @acces                    static public
         *
         * @returns                 boolean
         **/
        
        public static function destroy() {
            setcookie ("SynapsSessionId", "", time() - 3600); 
            unset($_COOKIE['SynapsSessionId']); 
                
                if(isset($_COOKIE['SynapsSessionId']) && !empty($_COOKIE['SynapsSessionId'])) {
                    throw new SessionException('Can\'t destroy session', SessionException::E_CORE_ERROR);
                    return false;
                } else {
                    self::$_iSessionId = null;
                    return true;
                }
        }
        
        
        /**
         * getType
         *        Returns type of given session
         *
         * @acces                    static public
         *
         * @returns                 string
         **/
        
        public static function getType($sKey) {
            $oCheckSessionType = Database::pdo()->prepare('SELECT sType
                                                            FROM s_binSessions
                                                                WHERE sKey = :sKey
                                                                AND sClientSessionId = :sClientSessionId
                                                                AND sClientIpAddress = :sClientIpAddress
                                                                    LIMIT 1');
                
                $oCheckSessionType->bindParam(':sKey', $sKey, PDO::PARAM_STR);
                $oCheckSessionType->bindParam(':sClientSessionId', self::$_iSessionId, PDO::PARAM_STR);
                    $sClientIpAddress = new IpAddress();
                $oCheckSessionType->bindParam(':sClientIpAddress', $sClientIpAddress->getIpAddress(), PDO::PARAM_STR);
            if($oCheckSessionType->execute()) {
                $rCheckSession = $oCheckSessionType->fetch(PDO::FETCH_ASSOC);
                    return $rCheckSession['sType'];
            } else {
                throw new SessionException('Can\'t return Type of a nonexisting session', SessionException::E_CORE_ERROR);
                return false;
            }
        }
        
        /**
         * getId
         *        Returns current session id
         *
         * @acces                    static public
         *
         * @returns                 string
         **/
        
        public static function getId() {
            return self::$_iSessionId;
        }
        
        /**
         * clone
         *
         * @acces                    public
         * 
         * @returns                 void
         **/
        
        public function __clone() {

        }
        
        
        /**
         * destruct
         *
         * @acces                    public
         * 
         * @returns                 void
         **/
        
        public function __destruct() {

        }
        
        
        /**
         * generateSessionId
         *        Generates a unique id using characters and numbers
         *
         * @acces                    private
         *
         * @returns                 string
         **/
        
        private function generateSessionId( ) {
            $sIdentity = '';
            $iIntegers = range(0,100);
            $sLowerCase = range('a','z');
            $sUpperCase = range('A','Z');
            
            $aChars = array_merge($iIntegers, $sLowerCase , $sUpperCase);
            
                for($i = 0; $i <= 50; $i++) {
                        $sIdentity .= $aChars[rand(0,count($aChars)-1)];
                }
            
            return sha1(microtime().$sIdentity);
        }
        
        /**
         * Type
         *        returns the type of value
         *
         * @acces                    static private
         *
         * @returns                 string
         **/
        
        private static function Type( $sValue ) {
            if(is_string($sValue)) {
                return 'String';
            } elseif(is_bool($sValue)) {
                return 'Boolean';
            } elseif(is_float($sValue)) {
                return 'Float';
            } elseif(is_int($sValue)) {
                return 'Integer';
            } elseif(is_object($sValue)) {
                return 'Object';
            } elseif(is_array($sValue)) {
                return 'Array';
            } else {
                return 'String';
            }
        }
}
?>

Commentaar

30-04-2010 18:18

Vraagje, wat heeft dit met sessions te maken?

http://www.php.net/manual/en/book.session.php

Dit is een systeem dat heel leuk sessions nadoet, maar meer ook niet mijns insziens. Waarom niet normale sessions gebruiken?

Daarnaast:
- in set() en get() controleer je niet of de queries gelukt zijn.
- waarom static?
- waarom singleton?
Voor zowel static als singleton zie ik geen reden moet ik zeggen...

1
2
3
Post hier de source-code van je script. Alle informatie tussen <? ... ?> en <?php ... ?> zal automatisch worden getoond in color-coding. 

Let op! Het is niet de bedoeling om hier een link naar je website te plaatsen. Post hier gewoon de code, veel simpeler, sneller en meer kans dat het blijft staan.
30-04-2010 18:33

In de get en set zal ik nog even controlers in bouwen op de queries.

Daarnaast Singleton en static omdat ik ook gewoon simpel in andere classes dit wil kunnen gebruiken.

Bij bijvoorbeeld een authorisatie classe. Dan kan ik een sessie aanmaken zonder die classe eerst weer te defineren. In mijn framework maak ik standaard gebruik van sessies. Dus in de index.php staat dan.

#load the Session class
Session::initialise();

En dan verder in de het framework kan ik dan altijd makkelijk een sessie setten.

Session::set('sKey', 'sValue');

etc etc.

Waarom een eigen session classe. Omdat het kan, een optie is waarvoor je kunt kiezen. Je kunt ook gewoon $_SESSION gebruiken. Het is net maar hoeveel controle je op dingen wilt en hoemeer functionaliteit je wilt. Je kunt deze namelijk met meer functionaliteiten uitbouwen met handige functies waardoor het schrijven van andere classes makkelijker zal gaan en er minder troep tussen zit om sessies om dingen te controleren etc etc etc..

Dus, nu ga ik koninginnedag vieren. xxx

1
2
3
Post hier de source-code van je script. Alle informatie tussen <? ... ?> en <?php ... ?> zal automatisch worden getoond in color-coding. 

Let op! Het is niet de bedoeling om hier een link naar je website te plaatsen. Post hier gewoon de code, veel simpeler, sneller en meer kans dat het blijft staan.
30-04-2010 21:26

- geen mogelijkheid om de session lifetime aan te passen
- geen garbage collector(!)

Je kunt onder water veel beter gebruik maken van session_set_save_handler(). Dan kun je verschillende classes maken voor verschillende manieren van opslag. Daarnaast kun je dan gebruik maken van de standaard session functionaliteiten zoals een garbage collector en je kunt jezelf heel wat queries besparen door alleen sessies weg te schrijven naar de database wanneer de script executie stopt en bij het readen alle sessie variabelen op te halen in plaats van een query per var.

Kijk eens naar Zend_Session in het Zend framework. Daar zie je een mooie implementatie met een save handler voor een database tabel.

Misschien moet je je sowieso afvragen waarom je een framework schrijft (tenzij je hiermee ervaring op wilt doen/van wilt leren).

1
2
3
Post hier de source-code van je script. Alle informatie tussen <? ... ?> en <?php ... ?> zal automatisch worden getoond in color-coding. 

Let op! Het is niet de bedoeling om hier een link naar je website te plaatsen. Post hier gewoon de code, veel simpeler, sneller en meer kans dat het blijft staan.
30-04-2010 21:52

Ik schrijf een framework gewoon voor de kennis/ervaring op te doen. Dus gewoon het wiel nog een keer uitvinden.

1
2
3
Post hier de source-code van je script. Alle informatie tussen <? ... ?> en <?php ... ?> zal automatisch worden getoond in color-coding. 

Let op! Het is niet de bedoeling om hier een link naar je website te plaatsen. Post hier gewoon de code, veel simpeler, sneller en meer kans dat het blijft staan.
01-05-2010 04:33

Goed bezig Pepijn (al heeft Vincent wel een puntje met naar database schrijven). Een heel goed alternatief voor $_SESSION.
Sessions worden op de meeste servers namelijk opgeslagen in een algemeen bereikbare temp dir. Iedereen kan dus alle sessions uitlezen. Garbage collection van standaard sessions is juist rotzooi en met een eigen oplossing kan je de TTL helemaal zelf controleren (ook al zit dat er niet in).

Waarom je de class statisch maakt snap ik wel, maar je mist zo wel een dingetje:
Je kan nu niet $_SESSION['bla']['oele'][2] ophalen in 1 keer. Toch?

Waarom je een object maakt, snap ik niet. Je kan de init ook gewoon statisch doen en statisch het ID opslaan. Singleton of niet. (Singleton is sowieso een debiel concept dat nooit iets toevoegt.)

Ik zou dat eerste dingetje dus toevoegen. Bijv door Session::get('bla.oele.2'). En als dat dan een object is (al weet ik niet hoe je die uit de database trekt, ook iets dat nu niet kan en met $_SESSION wel), kan je gewoon verder knutselen: Session::get(..)->getUser()->verify() etc

1
2
3
4
5
<?php

echo $_SESSION['oele']['bla'][2]->getUser()->username;

echo Session::get('oele.bla.2')->getUser()->username; // zal nooit werken (ook al implementeer je oele.bla.2)
01-05-2010 11:53

>>>
Daarnaast Singleton en static omdat ik ook gewoon simpel in andere classes dit wil kunnen gebruiken.
<<<
Maar waarom singleton? Static kan ik nog enigszins inkomen - zou het zelf niet doen, maar goed.

>>>
Dus in de index.php staat dan.

#load the Session class
Session::initialise();
<<<
oftewel: session_start();

>>>
En dan verder in de het framework kan ik dan altijd makkelijk een sessie setten.

Session::set('sKey', 'sValue');
<<<
oftewel: $_SESSION['sKey'] = 'sValue'; ;)

>>>
Waarom een eigen session classe. Omdat het kan, een optie is waarvoor je kunt kiezen. Je kunt ook gewoon $_SESSION gebruiken. Het is net maar hoeveel controle je op dingen wilt en hoemeer functionaliteit je wilt. Je kunt deze namelijk met meer functionaliteiten uitbouwen met handige functies waardoor het schrijven van andere classes makkelijker zal gaan en er minder troep tussen zit om sessies om dingen te controleren etc etc etc..
<<<

Ik heb absoluut niks tegen extra controle, noch tegen een leuke oefening (wat dit in essentie is [1]), maar het is bestaande functionaliteit die je nu aan het ontwikkelen bent. $_SESSION is globaal beschikbaar, je zou evt. globaal gewenste functionaliteit aan kunnen bieden - als die er niet al is - maar ik vraag me dan af wat zoiets zou moeten zijn.

Nogmaals, leuke oefening, leuk gedaan ook (al kunnen bv je comments wat uitgebreider, variable defenition bv., zie phpdoc ), maar of het daadwerkelijk ook iets toevoegd...

[1]= zie je andere reply :) Wat leuk zou zijn is als je all functionaliteit zou kopieren, bv ook sessen_regenerate_id() e.d. om het een daadwerkelijke, volledige db-based kopie te maken

1
2
3
Post hier de source-code van je script. Alle informatie tussen <? ... ?> en <?php ... ?> zal automatisch worden getoond in color-coding. 

Let op! Het is niet de bedoeling om hier een link naar je website te plaatsen. Post hier gewoon de code, veel simpeler, sneller en meer kans dat het blijft staan.
01-05-2010 12:33

Ik zal het qua functionaliteiten nog meer uitbreiden zoals jij al hebt aangegeven. Ook de suggesties van Rudie zal ik er nog in verwerken.

Ik snap dat Session::initialise(); hetzelfde is als session_start(); Waar ik snap niet waarom je hier een comment over maakt omdat ik met session_start natuurlijk niet mijn eigen sessie class start ;)

zoals eerder aangegeven, het is een keuze. Ik zeg ook niet dat $_SESSION niet te gebruiken is. Ik heb deze classe geschreven zodat ik gewoon met mijn eigen sessies kan werken en bij mijn nieuwe project dan ook hierin functionaliteiten kan bouwen die specifiek handig zijn voor een bepaald doeleinde.

1
2
3
Post hier de source-code van je script. Alle informatie tussen <? ... ?> en <?php ... ?> zal automatisch worden getoond in color-coding. 

Let op! Het is niet de bedoeling om hier een link naar je website te plaatsen. Post hier gewoon de code, veel simpeler, sneller en meer kans dat het blijft staan.
01-05-2010 13:21

>>>
Ik snap dat Session::initialise(); hetzelfde is als session_start(); Waar ik snap niet waarom je hier een comment over maakt omdat ik met session_start natuurlijk niet mijn eigen sessie class start ;)
<<<
Was puur om de overeenkomst tussen jouw db_based session en de "normale" $_SESSION aan te geven :)

>>>
[...] dan ook hierin functionaliteiten kan bouwen die specifiek handig zijn voor een bepaald doeleinde.
<<<
Ho ho, let op hè! OOP -> scheiding van verantwoordelijkheden. Dit is een hele mooie mogelijkheid om een generieke session class te bouwen, die erg herbruikbaar is. Ga die nu niet verpesten door er (9v/d10 keer) overbodige functionaliteit die meer app specifiek is in te bouwen.

1
2
3
Post hier de source-code van je script. Alle informatie tussen <? ... ?> en <?php ... ?> zal automatisch worden getoond in color-coding. 

Let op! Het is niet de bedoeling om hier een link naar je website te plaatsen. Post hier gewoon de code, veel simpeler, sneller en meer kans dat het blijft staan.
13-05-2010 13:53

Je gebruikt Database klasse maar er staat nergens code van de Database klasse. Zowiezo is het gebruik van databases icm sessies onbetrouwbaar. Als je database een request "mist" of gewoon eventjes down is, kan je sessions niet meer gebruiken.

1
2
3
Post hier de source-code van je script. Alle informatie tussen <? ... ?> en <?php ... ?> zal automatisch worden getoond in color-coding. 

Let op! Het is niet de bedoeling om hier een link naar je website te plaatsen. Post hier gewoon de code, veel simpeler, sneller en meer kans dat het blijft staan.
Inloggen wachtwoord vergeten? Aanmelden