Jump to content
Larry Ullman's Book Forums

Chapter 3 Session Handler Class Using Pdo Doesn'T Work As Intended


Recommended Posts

SOLVED

 

for solution see the last part of my first post

 

_______________________________________________________________________

hi , i read chapter 3 and try to pass session_set_save_handler with an object,

 

here's the code for my session handler class:

 

<?php

class MySessionHandler implements SessionHandlerInterface
{
    protected $conn = NULL;
    
    public function open($savePath, $sessionName)
    {
        if(is_null($this->conn))
        {
            $dsn = 'mysql:host=localhost;dbname=php_advanced';
            $username = 'root';
            $password = 'password';
            try
            {
                 $this->conn = new PDO($dsn, $username, $password);
                 $this->conn->setAttribute(PDO::ATTR_ERRMODE,PDO::ERRMODE_EXCEPTION);
            }
            catch(PDOException $e)
            {
                 $this->conn = NULL;
                 die('error in open function ' . $e->getMessage());
            }
        }
        return TRUE;
    }
    
    public function close()
    {
          
        echo '<p>close</p>';
        $this->conn = NULL;
        
        return TRUE;
    }
    
    public function read($id)
    {
          
        echo '<p>read</p>';
        $query = 'SELECT data FROM session_table WHERE session_id = :id';
        try
        {
            $pdo = $this->conn->prepare($query);
            $pdo->bindValue(':id', $id);
            $pdo->execute();
            
            //    Kalo query berhasil nemuin id..
            if($pdo->rowCount() == 1)
            {
                list($sessionData) = $pdo->fetch();
                
                return $sessionData;
            }
           
            return FALSE;
        }
        catch(PDOException $e)
        {
            $this->conn = NULL;
            die('error in read function => ' . $e->getMessage());
        }
        
    }
    
    public function write($id, $data)
    {
          
        echo '<p>write</p>';
        $query = 'REPLACE INTO session_table(session_id, data) VALUES(:id, :data)';
        
        try
        {
            $pdo = $this->conn->prepare($query);
            $pdo->bindValue(':id', $id);
            $pdo->bindValue(':data', $data);
            $pdo->execute();
            
            // return the value whether its success or not
            return (bool)$pdo->rowCount();
        }
        catch(PDOException $e)
        {
            $this->conn = NULL;
            die('error in write function => ' . $e->getMessage());
        }
    }
    
    public function destroy($id)
    {
          
        echo '<p>destroy</p>';
        $query = 'DELETE FROM session_table WHERE session_id = :id LIMIT 1';
        
        try
        {
            $pdo = $this->conn->prepare($query);
            $pdo->bindValue(':id', $id);
            $pdo->execute();
            $_SESSION = array();
            return (bool)$pdo->rowCount();
        }
        catch(PDOException $e)
        {
            $this->conn = NULL;
            die('error in destroy function => ' . $e->getMessage());
        }
    }

    public function gc($maxLifeTime)
    {
          
        echo '<p>garbage collection</p>';
        $query = 'DELETE FROM session_table WHERE DATE_ADD(last_accessed INTERVAL :time SECOND) < NOW()';
        
        try
        {
            $pdo = $this->conn->prepare($query);
            $pdo->bindValue(':time', $maxLifeTime);
            $pdo->execute();
            
            return TRUE;
        }
        catch(PDOException $e)
        {
            $this->conn = NULL;
            die('error in gc function => ' . $e->getMessage());
        }
    }
}

$SessionHandler = new MySessionHandler();
session_set_save_handler($SessionHandler);
session_name('my_session');

session_start();

 
 

 

 

i remove the session_write_close on purpose. This probably sounds stupid, but i want to get the session error to learn more..

 

here's session script(using Larry's code):


 


<?php

require('session_class.php');
?><!doctype html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <title>DB Session Test</title>
    <link rel="stylesheet" href="style.css">
</head>
<body>
<?php
// Store some dummy data in the session, if no data is present:
if (empty($_SESSION)) {

    $_SESSION['blah'] = 'umlaut';
    $_SESSION['this'] = 3615684.45;
    $_SESSION['that'] = 'blue';
    
    // Print a message indicating what's going on:
    echo '<p>Session data stored.</p>';
    
} else { // Print the already-stored data:
    echo '<p>Session Data Exists:<pre>' . print_r($_SESSION, 1) . '</pre></p>';
}

// Log the user out, if applicable:
if (isset($_GET['logout'])) {

    session_destroy();
    echo '<p>Session destroyed.</p>';
} else { // Otherwise, print the "Log Out" link:
    echo '<a href="session_link.php?logout=true">Log Out</a>';
}

// Reprint the session data:
echo '<p>Session Data:<pre>' . print_r($_SESSION, 1) . '</pre></p>';

// Complete the page:
echo '</body>
</html>';

// Write and close the session:
// session_write_close <<<<<--- I REMOVE THIS ON PURPOSE TO GET ERROR
?>
 

 

 

 

but i dont get any error, then i try to use Larry's mysqli script to connect db and it produces error..

 

can anyone explain why if im using PDO it doesn't generate error? i'm even dont use

 

register_shutdown_function('session_write_close');
 

in my session class destructor (on purpose)

 

NOTE : I'm doing this on purpose because i want to learn more.

 

the error im expecting is like when im using mysqli connection(connection closed  by php at the end of script then session try to write and close but no connection available) :

 


 

Warning: mysqli_real_escape_string() expects parameter 1 to be mysqli, null given in /var/www/ullman_advance/ch3/ullman_db.php on line 66



Warning: mysqli_real_escape_string() expects parameter 1 to be mysqli, null given in /var/www/ullman_advance/ch3/ullman_db.php on line 66



Warning: mysqli_query() expects parameter 1 to be mysqli, null given in /var/www/ullman_advance/ch3/ullman_db.php on line 67



Warning: mysqli_close() expects parameter 1 to be mysqli, null given in /var/www/ullman_advance/ch3/ullman_db.php on line 33
 

 

 

 

UPDATE

 

i just tried to pass session_set_save_handler with function callback(using pdo as connection) and it produces error i expected, but still if using MySessionHandler class it doesn't produce any error. The codes in the MySessionHandler class is similar with my new session handler functions.

 

here's the script

 

 

<?php

$conn = NULL;

function open_session()
{
    echo '<p>open session</p>';
    global $conn;
    $_dsn = 'mysql:host=localhost;dbname=php_advanced';
    $_username = 'root';
    $_password = 'monyetsahur';
    $conn = new PDO($_dsn, $_username, $_password);
    $conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
    
    return TRUE;
}

function close_session()
{
    echo '<p>close session</p>';
    global $conn;
    
    $conn = NULL;
    return TRUE;
}

function read_session($sid)
{
    echo '<p>read session</p>';
    global $conn;
    
    $query = 'SELECT data FROM session_table WHERE session_id = :sid';
    $pdo = $conn->prepare($query);
    $pdo->bindValue(':sid', $sid, PDO::PARAM_STR);
    $pdo->execute();
    
    if($pdo->rowCount() == 1)
    {
        list($session_data) = $pdo->fetch();
        echo '<pre>';
        print_r($session_data);
        echo '</pre>';
        
        return $session_data;
    }
    else
    {
        return '';
    }
}

 
function write_session($sid, $data)
{
    echo '<p>write session</p>';
    global $conn;
    
    $query = 'REPLACE INTO session_table(session_id, data) VALUES(:sid, :data)';
    $pdo = $conn->prepare($query);
    $pdo->bindValue(':sid', $sid, PDO::PARAM_STR);
    $pdo->bindValue(':data', $data, PDO::PARAM_STR);
    $pdo->execute();
    
    return (bool)$pdo->rowCount();
}

function destroy_session($sid)
{
    echo '<p>destroy session </p>';
    global $conn;
    
    $query = 'DELETE FROM session_table WHERE session_id = :sid';
    $pdo = $conn->prepare($query);
    $pdo->bindValue(':sid', $sid, PDO::PARAM_STR);
    $pdo->execute();
    
    // clean the session array;
    $_SESSION = array();
    
    return TRUE
}


function clean_session($expire)
{
    echo '<p>clean session</p>';
    global $conn;
    
    $query = 'DELETE FROM session_table WHERE DATE_ADD(last_accessed, INTERVAL :expire SECOND) < NOW()';
    
    $pdo = $conn->prepare($query);
    $pdo->bindValue(':expire', $expire, PDO::PARAM_INT);
    $pdo->execute();
    
    return $pdo->rowCount();
}
 
session_set_save_handler('open_session', 'close_session', 'read_session', 'write_session', 'destroy_session', 'clean_session');
session_name('my_session');
session_start();


SOLVED:

SOLVED


sorry guys my mistake actually
its a pretty easy answer why MySessionHandler class doesnt produce
error wihtout session_write_close() in the end of script,

session_set_save_handler() by default will register session_write_close() to register_shutdown_function()

so if u want to make your own shutdown function for session then use :

 


 

session_set_save_handler($SessionClass, FALSE)
 

 

 

 

if u do this then u must provide session_write_close() in your class destructor

source : http://php.net/manual/en/function.session-set-save-handler.php

thanks for the tips and your attention 

Link to comment
Share on other sites

Have you confirmed whether the changes are written to the session (the database) or not?

 

yes i have , its written in database using pdo and its even success accessing db session(using pdo) in the next browser request

 

i added

 

if($_SERVER['REQUEST_METHOD'] == 'POST')
{
    $_SESSION['post_data'] = $_POST['post_data'];
}

<form action="session_link.php" method="post">
    <input type="text" name="post_data" />
    <input type="submit" name="submit" value="store data" />
    
</form>
 

 

and confirmed that MySessionHandler() success storing the session data from $_POST method to the database

Link to comment
Share on other sites

SOLVED


sorry guys my mistake actually its a pretty easy answer why  MySessionHandler  class doesnt produce error wihtout session_write_close() in the end of script, 

session_set_save_handler() by default will register session_write_close() to register_shutdown_function()

so if u want to make your own shutdown function for session then use :

 

session_set_save_handler($SessionClass, FALSE)
 

 

if u do this then u must provide session_write_close() in your class destructor

source : http://php.net/manual/en/function.session-set-save-handler.php

thank you Larry for the support

Link to comment
Share on other sites

 Share

×
×
  • Create New...