Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: Własny session handler szwankuje
Forum PHP.pl > Forum > PHP > Object-oriented programming
Najki
Napisałem klasę obsługi sesji na bazie danych. Niestety problem polega na tym, że sesje zachowują się tak jak by gubiły dane przy każdym przeładowaniu strony. Identyfikator sesji jest chyba prawidłowo przekazywany, ponieważ php bez problemu odnajduje w bazie odpowiedni rekord i aktualizuje go w razie potrzeby, więc raczej ID sesji się nie gubi. Czyżbym robił coś źle? Złapałem bloka z tym, proszę o pomoc.

  1. <?php
  2.  
  3. class Sessions
  4. {
  5.  
  6. /**
  7. * @desc Przechowuje nazwe sesji.
  8. **/
  9. protected $session_name = '';
  10.  
  11. /**
  12. * @desc Przechowuje czas zycia sesji w sekundach.
  13. **/
  14. protected $session_expire = '';
  15.  
  16. /**
  17. * @desc Instancja klasy Database.
  18. **/
  19. protected $db;
  20.  
  21. /**
  22. * @desc Przechowuje nazwe tabeli w bazie danych
  23. **/
  24. protected $db_table;
  25.  
  26.  
  27. protected function __construct () { }
  28.  
  29. public function singleton ()
  30. {
  31. static $instance;
  32.  
  33. if(!isset($instance)) 
  34. {
  35. $instance = new Sessions;
  36. }
  37.  
  38. return $instance;
  39. }
  40.  
  41.  
  42.  
  43. /**
  44. * @desc Konstruktor. Pobiera dane, ustawia uchwyt sesji i uruchamia sesje.
  45. **/
  46. public function start ( $session_name = null, $session_expire = null, $db_table = null )
  47. {
  48. $this->db =& Database::singleton();
  49.  
  50. $default = array(
  51. 'session_name' => 'session', 
  52. 'session_expire' => 3600, 
  53. 'db_table' => 'sessions'
  54. );
  55.  
  56. $this->session_name = is_null($session_name) ? $default['session_name'] : $session_name;
  57. $this->session_expire = is_null($session_expire) ? $default['session_expire'] : $session_expire;
  58. $this->db_table = is_null($db_table) ? $default['db_table'] : $db_table;
  59.  
  60. array($this, 'open'),
  61. array($this, 'close'),
  62. array($this, 'read'),
  63. array($this, 'write'),
  64. array($this, 'destroy'),
  65. array($this, 'garbageCollector')
  66. );
  67.  
  68. session_name($this->session_name);
  69. }
  70.  
  71.  
  72. public function open ( $path, $name )
  73. {
  74. $this->name = $name;
  75. #$this->db->query('update `'.$this->db_table.'` set `last_updated`="'.mktime().'" where `id`="'.session_id().'";');
  76. return True;
  77. }
  78.  
  79.  
  80. public function close ()
  81. {
  82. $this->garbageCollector();
  83. return True;
  84. }
  85.  
  86.  
  87. public function read ( $sess_id )
  88. {
  89. $q = $this->db->query('select `data` from `'.$this->db_table.'` where `id`="'.$sess_id.'" and `last_updated`+'.$this->session_expire.' > UNIX_TIMESTAMP(NOW());');
  90. if ( $this->db->num($q) == 1 )
  91. {
  92. $r = $this->db->fetch($q);
  93. return $r['data'];
  94. }
  95. return '';
  96. }
  97.  
  98.  
  99. public function write ( $sess_id, $data )
  100. {
  101. if ( $this->db->query('insert into `'.$this->db_table.'` (`id`, `data`, `last_updated`, `ip`) values ("'.$sess_id.'", "'.$data.'", "'.mktime().'", "'.getIp().'");') )
  102. {
  103. return True;
  104. }
  105. else 
  106. {
  107. if ( $this->db->query('update `'.$this->db_table.'` set `data`="'.$data.'", `last_updated`="'.mktime().'" where `id`="'.session_id().'";') ) 
  108. {
  109. return True;
  110. }
  111. else 
  112. {
  113. return False;
  114. }
  115. }
  116. }
  117.  
  118.  
  119. public function destroy ( $sess_id )
  120. {
  121. return $this->db->query('delete from `'.$this->db_table.'` where `id`="'.$sess_id.'";');
  122. }
  123.  
  124.  
  125. public function garbageCollector ()
  126. {
  127. $this->db->query('delete from `'.$this->db_table.'` where `last_updated`+'.$this->session_expire.' <= UNIX_TIMESTAMP(NOW());');
  128. return;
  129. }
  130.  
  131. }
  132.  
  133. ?>
sobstel
jaka wersja php? bodaj od 5.0.4 albo 5.0.5 najpierw niszczone są wszystkie obiekty, przez co obiekt od bazy dany zamykany jest przed zamknięciem sesji (i utrwaleniem zmian). jest kilka sposób aby tego uniknąć np. register_shutdown_function('session_write_close') albo wywołanie funkcji session_write_close() na końcu itp. poszukaj na bugs.php.net, tam jest trochę więcej o tym (oczywiście jeśli to jest problemem w twoim przypadku)
nrm
za malo danych podales, ciezko tak strzelic co moze byc nie tak. ale porownujac do swoich sesji to powiem ci, ze mam ciut inaczej:

w read(); jesli jest sesja odczytana to ustawiam jestsesja = true
w write(); jesli jestsesja = true to sie robi update, jesli false to sie robi insert.

w zasadzie masz podobnie oprocz tego ze bazujesz tylko na tym czy uda sie zrobic insert. jesli w bazie pole sessid nie bedzie unique to tym sposobem zawsze nainsertujesz sobie mase tych samych sesji.

przydalo by ci sie tez jakies sprawdzanie danych bo nie mozna wiezyc temu z czego sie czyta sesje smile.gif
sobstel
Cytat(normanos @ 2006-02-27 13:30:46)
w read(); jesli jest sesja odczytana to ustawiam jestsesja = true
w write(); jesli jestsesja = true to sie robi update, jesli false to sie robi insert.

w MySQLu mozna ten krok skrócić to jednego zapytania REPLACE
Najki
Mam php 5.0.3.

1) register_shutdown_function('session_write_close') nie pomogło.
2) session_write_close() na końcu index.php też nie pomogło.

W każdym razie - fakt, za mało informacji podałem, ale co jeszcze może się przydać? phpinfo() ?

Problemem nie jest raczej baza danych, bo dane się dopisują, ale nie są przesyłane między stronami. Na każdej następnej wywołanej stronie tablica $_SESSION jest pusta. Odpowiednią zawartość ma tylko i wyłącznie na stronie, na której została ustawiona (moment zalogowania się).

Daję standardowo session_register('id','username','password') i ustawiam ich wartości. Na kolejnych stronach ich już nie widać.

normanos: pole id jest ustawione jako indeks, czyli wychodzi na to samo jak z unique.

Jeśli to ma jakieś znaczenie, klasa ta jest fragmentem budowanego przeze mnie framework'a, który działa na NiceURL'ach. To coś zmienia, że NiceURL? Może sesja gubi się na adresie, czy cuś?

UPDATE:
Hm, to chyba jednak dość indywidualny problem, bo sprawdziłem dokładniej tą klasę i faktycznie działa prawidłowo, ale moja implementacja tej klasy we framework'u, którego piszę nie działa, a trochę głupio wrzucać źródło wuchty plików i prosić o sprawdzanie ich po kolei, nie? smile.gif Chyba jestem zdany na siebie.

UPDATE2:
Problem rozwiązany. Bezsens trochę. Oto o co poszło:
http://pl.php.net/manual/pl/function.sessi...ndler.php#41365
eS...
[OT]
czy w
  1. <?php
  2.  
  3. array(&$this, 'open'),//nie powinno byc &
  4.  
  5. ?>

jest późno wiec cos pewnie mi sie ..... jeszcze raz sory za OT
[/OT]
To jest wersja lo-fi głównej zawartości. Aby zobaczyć pełną wersję z większą zawartością, obrazkami i formatowaniem proszę kliknij tutaj.
Invision Power Board © 2001-2025 Invision Power Services, Inc.