php.de

Zurück   php.de > Webentwicklung > Software-Design

Software-Design Diskussionen auf Profi-Niveau: PHP Lösungen auf konzeptioneller Ebene

Antwort
 
LinkBack Themen-Optionen Thema bewerten
Alt 27.03.2009, 01:13  
Erfahrener Benutzer
 
Registriert seit: 06.09.2008
Beiträge: 189
#Avedo befindet sich auf einem aufstrebenden Ast
Standard SessionHandler - Sessions in einer Datenbank

Hallo!
Da ich gerade beim Thema Benutzerverwaltung etwas auf der Stelle trete wollte ich mich erstmal verwandten Themen zuwenden. Da ich vor wenigen Tagen im PHP Manual auf die Funktion session_set_save_handler() gestoßen bin, habe ich mir überlegt anstatt der im Manual vorgestellten Funktionen eine Klasse zu schreiben, die es mir ermöglich Sessions in einer Datenbank zu speichern. Ich habe also die Funktionen in eine Klasse gepackt und mit Datenbank Anfragen gefüllt. Das ist mir denke ich auch ganz gut gelungen. Um das ganze zu verwenden arbeitet man eigentlich ganz normal mit den Sessions. Man muss zuvor nur eine Instanz der Klasse erzeugen.
PHP-Code:
/* instance SessionHandler */
new SessionHandler();
    
/* assign some values to the session */
$_SESSION['name'] = 'avedo';
$_SESSION['mail'] = 'avedo@web.de';
    
/* get some session value */
echo 'logged in as ' $_SESSION['name'];
    
/* delete session */
session_destroy(); 
Leider bin ich mir noch nicht so recht sicher, ob ich die Funktion register_shutdown_function() korrekt verwendet habe. Wäre nett, wenn jemand sich das mal anschauen könnte. Ihr findet den Aufruf bzw. die Aufrufe der Funktion im Konstruktor der Klasse.

Würde mich natürlich auch über Rückmeldungen und Stellungnahmen zu dieser Klasse freuen.

MfG, Andy

PHP-Code:
/**
 * Class SessionHandler
 * 
 * The SessionHandler class imlements all methods to use a 
 * database based session management instead of using text files. 
 * This has the benefit thatt all session data can be accessed
 * at a central place. This class is supported since the PHP version 5.0.5 
 * because it uses the register_shutdown_function() function to ensure that 
 * all session values are stored before the PHP representation is destroyed.
 * 
 * @package SessionHandler
 * @version 0.1
 * @author Andreas Wilhelm <Andreas2209@web.de>
 * @copyright Andreas Wilhelm 
 * @link http://avedo.net
 */  
class SessionHandler
{
    
/**
     * @var mysqli $mysqli The MySQLi object that is used to access the database
     * @access private
     */
    
private $mysqli null;

    
/**
     * Sets the user-level session storage functions which are used 
     * for storing and retrieving data associated with a session.
     *
     * @access public
     * @param mysqli $mysqli The MySQLi object that is used to access the database
     * @return void
     */
    
public function __construct(mysqli $mysqli)
    {
        
/* assign the mysqli object */
        
$this->mysqli $mysqli
    
        
/* set session handler to the class methods */
        
session_set_save_handler(
            array(
$this'open'),
            array(
$this'close'),
            array(
$this'read'),
            array(
$this'write'),
            array(
$this'destroy'),
            array(
$this'gc')
        );
        
        
/* start a new session */
        
session_start();
        
        
/* make sure that the session values are stored */
        
register_shutdown_function( array($this'write') );
        
register_shutdown_function( array($this'close') );
    }
    
    
/**
     * Is called to open a session. The method 
     * does nothing because we do not want to write
     * into a file so we doesn't need to open one.
     *
     * @access public
     * @param String $save_path The save path
     * @param String $session_name The name of the session
     * @return Boolean
     */
    
public function open($save_path$session_name)
    {
        return 
true;
    }
    
    
/**
     * Is called when the reading in a session is 
     * completed. The method calls the garbage collector. 
     *
     * @access public
     * @return Boolean
     */
    
public function close()
    {
        
/* call the garbage collector */
        
$this->gc(0);
        
        return 
true;
    }
    
    
/**
     * Is called to read data from a session.
     *
     * @access public
     * @access Integer $id The id of the current session
     * @return Mixed
     */
    
public function read($id)
    {
        
/* create a query to get the session data */
        
$select "SELECT 
                * 
            FROM 
                sessions
            WHERE
                id = '" 
$id "'
            LIMIT 1;"
;
        
        
/* send select statement */
        
$result $this->mysqli->query($select);
        
        
/* a session was found */
        
if( count($result) > )
        {
            return 
$result[0]["value"]
        }
        
        
/* no session found */
        
return '';
    }
    
    
/**
     * Writes data into a session rather 
     * into the session record in the database.
     *
     * @access public
     * @access Integer $id The id of the current session
     * @access String $sess_data The data of the session
     * @return Boolean
     */
    
public function write($id$sess_data)
    {
        
/* check if some data was given */
        
if( $sess_data == null )
        {
            return 
true;
        }
    
        
/* query to update a session */
        
$update "UPDATE
                sessions 
            SET
                last_updated = '" 
.time() . "',
                value = '" 
$sess_data "'
            WHERE
                id =  = '" 
$id "';";
        
        
/* send select statement */
        
$result $this->mysqli->query($update);
        
        
/* database error */
        
if( $result === false )
        {
            return 
false;
        }
        
        
/* current session was updated */
        
if( $this->mysqli->affected_rows )
        {
            return 
true;
        }
        
        
/* session does not exists create insert statement */
        
$insert "INSERT INTO 
                sessions 
                (id, last_updated, start, value)
            VALUES
                ('" 
$id "', '" time() . "', '" time() . "', '" $sess_data "');";
                
        
/* send insert statement */
        
$result $this->mysqli->query($insert);
        
        return 
$result;
    }
    
    
/**
     * Ends a session and deletes it.
     *
     * @access public
     * @access Integer $id The id of the current session
     * @return Boolean
     */
    
public function destroy($id)
    {
        
/* create a query to delete a session */
        
$delete "DELETE FROM
                sessions
            WHERE
                id = '" 
$id "';";
                
        
/* send delete statement */
        
$result $this->mysqli->query($delete);
        
        return 
$result;
    }
    
    
/**
     * The garbage collector deletes all sessions from the database 
     * that where not deleted by the session_destroy function.
     * so your session table will be stay clean.
     *
     * @access public
     * @access Integer $maxlifetime The maximum session lifetime
     * @return Boolean
     */
    
public function gc($maxlifetime)
    {
        
/* period after that a session pass off */
        
$maxlifetime strtotime("-20 minutes");
        
        
/* delete statement */
        
$delete "DELETE FROM
                sessions
            WHERE
                last_updated < '" 
$maxlifetime "';";

        
/* send delete statement */
        
$result $this->mysqli->query($delete);
        
        return 
$result;
    }

__________________
I'm so tired of slitting the throats of people calling me a violent psychopath.

Geändert von #Avedo (27.03.2009 um 12:58 Uhr).
#Avedo ist offline   Mit Zitat antworten
Sponsor Mitteilung
PHP Code Flüsterer

Registriert seit: 21.08.2005
Beiträge: 4682
PHP-Kenntnisse:
Fortgeschritten

Alt 27.03.2009, 11:03  
Erfahrener Benutzer
 
Registriert seit: 06.01.2009
Beiträge: 145
nuna befindet sich auf einem aufstrebenden Ast
Standard

Ich lese in jedem Buch, dass die read-Methode einen String zurückgeben muss.

PHP-Code:
        /* a session was found */
        
if( count($result) > )
        {
            return 
$result[0]["value"]
        }
        
        
/* no session found, return empty string */
        
return ''
Ansonsten produziert es einen Error.
nuna ist offline   Mit Zitat antworten
Alt 27.03.2009, 11:23  
Erfahrener Benutzer
 
Benutzerbild von Phoscur
 
Registriert seit: 01.12.2008
Beiträge: 450
PHP-Kenntnisse:
Fortgeschritten
Phoscur wird schon bald berühmt werdenPhoscur wird schon bald berühmt werden
Standard

Ich habe auch eine Session Klasse, in welche ich, je nach Bedarf einmal einen datenbankbasierten Mechanismus einbauen kann. Ich hatte noch eine nette Idee um allgemein Objektcaching und die Sessionverwaltung zu vereinfachen.

1. Singleton für die Sessionklasse (Das sollte dann auch das wiederholte starten einer Session vermeiden).
2. Interface Arrayaccess für die Sessionklasse und eine Implementierung, die Set der Sessionklasse in $_SESSION['objectsave'][irgendeineID] speichert.
Get entserialisiert dementspreched.

Sry, ist nicht ganz im Thema, dennoch passend hoffe ich.
__________________
Phoscur ist offline   Mit Zitat antworten
Alt 27.03.2009, 13:09  
Erfahrener Benutzer
 
Registriert seit: 06.09.2008
Beiträge: 189
#Avedo befindet sich auf einem aufstrebenden Ast
Standard

@nuna
Danke habe ich übersehen. Ich habe es oben in der Klasse mal geändert.

@Phlegma
Mir fehlt noch irgendwie der Sinn deiner 2. Erweiterung zum das ganze nicht wirklich hilfreich ist, wenn man irgendeine Id verwendet. So würden sich Objekte mit der gleichen Id, aber verschiedenen Inhalten überschreiben. Das einzige was hier sinn machen würde wäre ein Hash des Objekts als Index.
PHP-Code:
md5(serialize($obj)) 
oder
PHP-Code:
md5(implode(get_object_vars($obj))) 
Ein Singletone macht natürlich Sinn. Ich verwende jedoch eine Singletone bzw. eine Registry Klasse, die das Singletone Pattern implementiert. Daher wird eine direkte Implementierung des Patterns überflüssig.

@Topic
Kann mir noch jemand sagen, ob die Funktion register_shutdown_function() korrekt verwendet habe? WÜrde mich natürlich auch über weitere Anmerkungen und Kommentare freuen.

MfG, Andy
__________________
I'm so tired of slitting the throats of people calling me a violent psychopath.
#Avedo ist offline   Mit Zitat antworten
Alt 27.03.2009, 13:19  
Erfahrener Benutzer
 
Benutzerbild von Phoscur
 
Registriert seit: 01.12.2008
Beiträge: 450
PHP-Kenntnisse:
Fortgeschritten
Phoscur wird schon bald berühmt werdenPhoscur wird schon bald berühmt werden
Standard

Ach, das kann man machen wie man will. Natürlich sollte sie eindeutig sein! md5 ist mir allerdings dann zu verschwenderisch...
Ich würde sie wahrscheinlich nach Klassen geördnet und mithilfe der sql ID speichern, kein Overhead fürs hashen.

Zu register_shutdown_function: Ich denke schon. Probiers doch aus, testen musst du sowieso alles.
__________________
Phoscur ist offline   Mit Zitat antworten
Alt 27.03.2009, 13:22  
moderatives Dielektrikum
 
Benutzerbild von nikosch
 
Registriert seit: 21.05.2008
Beiträge: 35.994
PHP-Kenntnisse:
Fortgeschritten
nikosch hat eine strahlende Zukunftnikosch hat eine strahlende Zukunftnikosch hat eine strahlende Zukunftnikosch hat eine strahlende Zukunftnikosch hat eine strahlende Zukunftnikosch hat eine strahlende Zukunftnikosch hat eine strahlende Zukunftnikosch hat eine strahlende Zukunftnikosch hat eine strahlende Zukunftnikosch hat eine strahlende Zukunftnikosch hat eine strahlende Zukunft
Standard

Zitat:
md5 ist mir allerdings dann zu verschwenderisch...
Das meinte Doc neulich auch schon. Der Vorteil ist natürlich, dass man mit einem Hash aus dem serialisierten Objekt herausfindet, ob sich dessen Eigenschaften geändert haben. (Caching etc.)
__________________
--
One pixel is still too big. Please make it smaller. ASAP.

Initiative Mittelstand.
Die wichtigste Gestaltungsregel im Screendesign ist Pi mal Daumen des Arbeitgebers.
--
nikosch ist gerade online   Mit Zitat antworten
Alt 27.03.2009, 13:33  
Erfahrener Benutzer
 
Benutzerbild von Phoscur
 
Registriert seit: 01.12.2008
Beiträge: 450
PHP-Kenntnisse:
Fortgeschritten
Phoscur wird schon bald berühmt werdenPhoscur wird schon bald berühmt werden
Standard

Naja geht das auch nicht einfach mit einem array == array?
Ich generiere das DB Update mit einem array_diff-basierten Algorithmus, geht eigentllich recht schnell. Caching wollte ich mit einem Dekorierer über dem Mapper realisieren.
__________________
Phoscur ist offline   Mit Zitat antworten
Alt 27.03.2009, 13:50  
moderatives Dielektrikum
 
Benutzerbild von nikosch
 
Registriert seit: 21.05.2008
Beiträge: 35.994
PHP-Kenntnisse:
Fortgeschritten
nikosch hat eine strahlende Zukunftnikosch hat eine strahlende Zukunftnikosch hat eine strahlende Zukunftnikosch hat eine strahlende Zukunftnikosch hat eine strahlende Zukunftnikosch hat eine strahlende Zukunftnikosch hat eine strahlende Zukunftnikosch hat eine strahlende Zukunftnikosch hat eine strahlende Zukunftnikosch hat eine strahlende Zukunftnikosch hat eine strahlende Zukunft
Standard

Solange Du alles geladen hast, was Du vergleichen willst, geht das bestimmt. Bzw. einen Vergleichswert hast. Wenn DU jetzt entscheiden mußt, ob ein Singleton neu gespeichert werden muß, siehts imho eher schlecht aus..
__________________
--
One pixel is still too big. Please make it smaller. ASAP.

Initiative Mittelstand.
Die wichtigste Gestaltungsregel im Screendesign ist Pi mal Daumen des Arbeitgebers.
--
nikosch ist gerade online   Mit Zitat antworten
Alt 27.03.2009, 18:59  
Moderator und Wett-König
 
Benutzerbild von dr.e.
 
Registriert seit: 21.05.2008
Beiträge: 3.657
PHP-Kenntnisse:
Fortgeschritten
dr.e. ist ein Lichtblickdr.e. ist ein Lichtblickdr.e. ist ein Lichtblickdr.e. ist ein Lichtblickdr.e. ist ein Lichtblickdr.e. ist ein Lichtblick
dr.e. eine Nachricht über Skype™ schicken
Standard

Ich schließe mich Phlegma an. Wenn du den Aufwand schon treibst, dann gestalte das Speicher-Backend generisch. Sprich: der SessionManager ist ein allgemeines Interface zum Entwickler hin, hat jedoch Persistenz-Schichten, an die die eigentliche Arbeit deligiert wird. Ansätze dazu unter Klassen-Referenz - CacheManager :: Adventure PHP Framework (APF)
__________________
Viele Grüße,
Dr.E.

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1. Think about software design before you start to write code!
2. Discuss and review it together with experts!
3. Choose good tools (-> Adventure PHP Framework (APF))!
4. Write clean and reusable software only!
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
dr.e. ist offline   Mit Zitat antworten
Alt 28.03.2009, 11:23  
Erfahrener Benutzer
 
Registriert seit: 06.09.2008
Beiträge: 189
#Avedo befindet sich auf einem aufstrebenden Ast
Standard

Ich sehe leider noch nicht so ganz was mir das bringen soll. Natürlich könnte ich ein allgemeines Interface SessionHandler schreiben, dass sähe dann wohl wie folgt aus:
PHP-Code:
interface SessionHandler
{
     public function 
open($save_path$session_name);
     public function 
close();
     public function 
read($id);
     public function 
write($id$sess_data);
     public function 
destroy($id);
     public function 
gc($maxlifetime);

Dann müsste ich natürlich noch die SessionHandler Klasse umbenennen in DatabaseCache oder so und den Klassen-Kopf, wie folgt ändern:
PHP-Code:
class DatabaseCache implements SessionHandler
{
     ...

Das habe ich doch alles so richtig verstanden. Doch was bringt es mir zu einem Datenbank basierten SessionHandler noch einen Dateisystem basierten SessionHandler zu schreiben. Ist der nicht einerseits viel leichter angreifbar und zudem auch noch schlechter erreichbar? Möchte ich zum Beispiel alle Nutzer, die momentan auf meinen Seiten sind abfragen, so kann ich auch direkt an die Tabelle sessions herantreten anstatt über die Sitzungsverwaltung zu gehen. Wäre nett, wenn mir noch jemand etwas genauer erklären könnte, was man damit bezweckt.

MfG, Andy
__________________
I'm so tired of slitting the throats of people calling me a violent psychopath.
#Avedo ist offline   Mit Zitat antworten
Antwort


Themen-Optionen
Thema bewerten
Thema bewerten:

Forumregeln
Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are an
Gehe zu

Ähnliche Themen
Thema Autor Forum Antworten Letzter Beitrag
[Erledigt] Merkwürdiges Verhalten bei Datenbank basierten Sessions Chestarbargel PHP-Fortgeschrittene 11 05.09.2008 08:16
Direkten Zugriff auf Datenbank verhindern heyho PHP Tipps 2008 7 07.02.2008 11:41
schribt nichts in die datenbank Cheesy92 PHP Tipps 2006 9 27.10.2006 14:03
Verbindung zu einer Datenbank im LAN Datenbanken 11 25.09.2005 12:18
Mehrere Anwendungen eine Datenbank... Datenbanken 5 15.08.2005 11:22
mysql datenbank anlegen...aber WIE??? Datenbanken 0 05.08.2005 19:33
[Erledigt] mysql datenbank anlegen...aber WIE??? PHP Tipps 2005-2 0 05.08.2005 19:33
mysql datenbank anlegen...aber WIE??? Datenbanken 0 05.08.2005 19:32
mysql datenbank anlegen...aber WIE??? Datenbanken 0 05.08.2005 19:31
[Erledigt] mysql datenbank anlegen...aber WIE??? Datenbanken 0 05.08.2005 19:31
[Erledigt] mysql datenbank anlegen...aber WIE??? Datenbanken 0 05.08.2005 19:29
mysql datenbank anlegen...aber WIE??? Datenbanken 0 05.08.2005 19:29
Eintrag in Datenbank mittels Formular? Datenbanken 5 16.12.2004 17:36
Wie sicher sind Sessions? PHP Tipps 2004 6 02.11.2004 09:26
Sessions, sessions und nochmal sessions PHP-Fortgeschrittene 0 06.06.2004 00:36

Besucher kamen über folgende Suchanfragen bei Google auf diese Seite
session handler, php session handler, sessionhandler, session datenbank, session in datenbank, php sessionhandler, php session datenbank, session handler php, php session handling, session_handler, php session handler class, session handler class, php session database, php session class, sessionhandler php mysql, session mit datenbank, http://www.php.de/software-design/53421-sessionhandler-sessions-einer-datenbank.html, php class sessionhandler, php mysql session handler, php session in datenbank

Alle Zeitangaben in WEZ +2. Es ist jetzt 00:33 Uhr.




Powered by vBulletin® Version 3.7.2 (Deutsch)
Copyright ©2000 - 2012, Jelsoft Enterprises Ltd.
Search Engine Optimization by vBSEO 3.2.0
Aprilia-Forum, Aquaristik-Forum, Liebeskummer-Forum, Zierfisch-Forum, Geizkragen-Forum