Through a custom session .
To create a custom session handler, use the session_set_save_handler ()
The below handler, based on MySQLi, will use a simple SQL structure:
CREATE TABLE 'session_data' (
'id' varchar(32) NOT NULL,
'data' text,
'last_updated' timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY ('id')
) ENGINE=InnoDB DEFAULT CHARSET=utf8_unicode_ci;
The handler :
class SessionSaveHandler {
protected $link;
protected $table;
protected $sessionName = 'session';
protected $maxLifeTime = 3600;
public function __construct( $user = null, $pass = null, $host = null, $db = null, $table = null, $sessionName = null ) {
$this -> link = mysqli_connect( $host, $user, $pass, $db );
if( ! $this -> link ) {
throw new Exception( 'Could not connect to the database!' );
}
mysqli_select_db( $this -> link, $db );
session_set_save_handler(
array( $this, 'open' ),
array( $this, 'close' ),
array( $this, 'read' ),
array( $this, 'write' ),
array( $this, 'destroy' ),
array( $this, 'gc' )
);
$this -> table = $table;
session_name( $this -> sessionName );
session_start();
}
public function open( $savePath, $sessionName ) {
$this -> sessionName = $sessionName;
return TRUE;
}
public function close() {
return true;
}
public function read( $id ) {
$query = sprintf(
'SELECT 'data' FROM %s WHERE 'id' = ? AND UNIX_TIMESTAMP( 'last_updated' ) + %d > UNIX_TIMESTAMP( NOW() )',
$this -> table, $this -> maxLifeTime
);
$stmt = mysqli_prepare( $this -> link, $query );
mysqli_stmt_bind_param( $stmt, 's', $id );
if( mysqli_execute( $stmt ) ) {
mysqli_stmt_bind_result( $stmt, $retval );
mysqli_stmt_fetch( $stmt );
if( ! empty( $retval ) ) return $retval;
}
return '';
}
public function write( $id, $data ) {
$query = sprintf(
'INSERT INTO %s (id, data) VALUES (?, ?) ON DUPLICATE KEY UPDATE data = ?, last_updated=NULL',
$this -> table
);
$stmt = mysqli_prepare( $this -> link, $query );
mysqli_stmt_bind_param( $stmt, 'sss', $id, $data, $data );
return mysqli_execute( $stmt );
}
public function destroy( $id ) {
$query = sprintf( 'DELETE FROM %s WHERE id = ?', $this -> table );
$stmt = mysqli_prepare( $this -> link, $query );
mysqli_stmt_bind_param( $stmt, 's', $id );
return mysqli_execute( $stmt );
}
public function gc( $maxlifetime ) {
$query = sprintf(
'DELETE FROM %s WHERE UNIX_TIMESTAMP( last_updated ) + %d <= UNIX_TIMESTAMP( NOW() )',
$this -> table, $this -> maxLifeTime
);
mysqli_query( $this -> link, $query );
return;
}
}
And its use:
require_once 'handler.php';
new SessionSaveHandler( 'root', '7v4h6q7t', 'localhost', 'session', 'session_data' );
$_SESSION['name'] = 'Bruno Augusto'; // write
$_SESSION['age'] = 26; // write
var_dump( $_SESSION['name'] ); // read
unset( $_SESSION['age'] );
var_dump( $_SESSION ); // proof
This generic handler allows session data to be written, read, and manipulated in a database. Point!
Now what really really is the scope of the topic is to customize the behavior. Simply add a new column to the table to make the condition conform to the reference link that raised the doubt and modify the queries of the SessionHandler :: write () and SessionHandler methods: read () (for security) to take it into account.
In this way, when creating the session variable, thus firing the SessionHandler :: write () method, the index will only be created if the existence condition is satisfied.
And thanks to it, when checking if the index of the session exists to release access to the particular page, by having even been created, everything solves itself practically alone.