added a dbal session storage
This commit is contained in:
parent
c5e0c80a76
commit
a1888b2f01
@ -0,0 +1,205 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Symfony\Bridge\Doctrine\HttpFoundation;
|
||||||
|
|
||||||
|
use Doctrine\DBAL\Platforms\MySqlPlatform;
|
||||||
|
|
||||||
|
use Symfony\Component\HttpFoundation\SessionStorage\NativeSessionStorage;
|
||||||
|
use Doctrine\DBAL\Driver\Connection;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* DBAL based session storage.
|
||||||
|
*
|
||||||
|
* @author Fabien Potencier <fabien@symfony.com>
|
||||||
|
* @author Johannes M. Schmitt <schmittjoh@gmail.com>
|
||||||
|
*/
|
||||||
|
class DbalSessionStorage extends NativeSessionStorage
|
||||||
|
{
|
||||||
|
private $con;
|
||||||
|
private $tableName;
|
||||||
|
|
||||||
|
public function __construct(Connection $con, $tableName = 'sessions', array $options = array())
|
||||||
|
{
|
||||||
|
parent::__construct($options);
|
||||||
|
|
||||||
|
$this->con = $con;
|
||||||
|
$this->tableName = $tableName;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Starts the session.
|
||||||
|
*/
|
||||||
|
public function start()
|
||||||
|
{
|
||||||
|
if (self::$sessionStarted) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// use this object as the session handler
|
||||||
|
session_set_save_handler(
|
||||||
|
array($this, 'sessionOpen'),
|
||||||
|
array($this, 'sessionClose'),
|
||||||
|
array($this, 'sessionRead'),
|
||||||
|
array($this, 'sessionWrite'),
|
||||||
|
array($this, 'sessionDestroy'),
|
||||||
|
array($this, 'sessionGC')
|
||||||
|
);
|
||||||
|
|
||||||
|
parent::start();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Opens a session.
|
||||||
|
*
|
||||||
|
* @param string $path (ignored)
|
||||||
|
* @param string $name (ignored)
|
||||||
|
*
|
||||||
|
* @return Boolean true, if the session was opened, otherwise an exception is thrown
|
||||||
|
*/
|
||||||
|
public function sessionOpen($path = null, $name = null)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Closes a session.
|
||||||
|
*
|
||||||
|
* @return Boolean true, if the session was closed, otherwise false
|
||||||
|
*/
|
||||||
|
public function sessionClose()
|
||||||
|
{
|
||||||
|
// do nothing
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Destroys a session.
|
||||||
|
*
|
||||||
|
* @param string $id A session ID
|
||||||
|
*
|
||||||
|
* @return Boolean true, if the session was destroyed, otherwise an exception is thrown
|
||||||
|
*
|
||||||
|
* @throws \RuntimeException If the session cannot be destroyed
|
||||||
|
*/
|
||||||
|
public function sessionDestroy($id)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$this->con->executeQuery("DELETE FROM {$this->tableName} WHERE sess_id = :id", array(
|
||||||
|
'id' => $id,
|
||||||
|
));
|
||||||
|
} catch (\PDOException $e) {
|
||||||
|
throw new \RuntimeException(sprintf('PDOException was thrown when trying to manipulate session data: %s', $e->getMessage()), 0, $e);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cleans up old sessions.
|
||||||
|
*
|
||||||
|
* @param int $lifetime The lifetime of a session
|
||||||
|
*
|
||||||
|
* @return Boolean true, if old sessions have been cleaned, otherwise an exception is thrown
|
||||||
|
*
|
||||||
|
* @throws \RuntimeException If any old sessions cannot be cleaned
|
||||||
|
*/
|
||||||
|
public function sessionGC($lifetime)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$this->con->executeQuery("DELETE FROM {$this->tableName} WHERE sess_time < :time", array(
|
||||||
|
'time' => time() - $this->options['lifetime'],
|
||||||
|
));
|
||||||
|
} catch (\PDOException $e) {
|
||||||
|
throw new \RuntimeException(sprintf('PDOException was thrown when trying to manipulate session data: %s', $e->getMessage()), 0, $e);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reads a session.
|
||||||
|
*
|
||||||
|
* @param string $id A session ID
|
||||||
|
*
|
||||||
|
* @return string The session data if the session was read or created, otherwise an exception is thrown
|
||||||
|
*
|
||||||
|
* @throws \RuntimeException If the session cannot be read
|
||||||
|
*/
|
||||||
|
public function sessionRead($id)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$data = $this->con->executeQuery("SELECT sess_data FROM {$this->tableName} WHERE sess_id = :id", array(
|
||||||
|
'id' => $id,
|
||||||
|
))->fetchColumn();
|
||||||
|
|
||||||
|
if (false !== $data) {
|
||||||
|
return $data;
|
||||||
|
}
|
||||||
|
|
||||||
|
// session does not exist, create it
|
||||||
|
$this->createNewSession($id);
|
||||||
|
|
||||||
|
return '';
|
||||||
|
} catch (\PDOException $e) {
|
||||||
|
throw new \RuntimeException(sprintf('PDOException was thrown when trying to manipulate session data: %s', $e->getMessage()), 0, $e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Writes session data.
|
||||||
|
*
|
||||||
|
* @param string $id A session ID
|
||||||
|
* @param string $data A serialized chunk of session data
|
||||||
|
*
|
||||||
|
* @return Boolean true, if the session was written, otherwise an exception is thrown
|
||||||
|
*
|
||||||
|
* @throws \RuntimeException If the session data cannot be written
|
||||||
|
*/
|
||||||
|
public function sessionWrite($id, $data)
|
||||||
|
{
|
||||||
|
$platform = $this->con->getDatabasePlatform();
|
||||||
|
|
||||||
|
// this should maybe be abstracted in Doctrine DBAL
|
||||||
|
if ($platform instanceof MySqlPlatform) {
|
||||||
|
$sql = "INSERT INTO {$this->tableName} (sess_id, sess_data, sess_time) VALUES (:id, :data, :time) "
|
||||||
|
."ON DUPLICATE KEY UPDATE sess_data = VALUES(sess_data), sess_time = CASE WHEN sess_time = :time THEN (VALUES(sess_time) + 1) ELSE VALUES(sess_time) END";
|
||||||
|
} else {
|
||||||
|
$sql = "UPDATE {$this->tableName} SET sess_data = :data, sess_time = :time WHERE sess_id = :id";
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
$stmt = $this->con->executeQuery($sql, array(
|
||||||
|
'id' => $id,
|
||||||
|
'data' => $data,
|
||||||
|
'time' => time(),
|
||||||
|
));
|
||||||
|
|
||||||
|
if (!$stmt->rowCount()) {
|
||||||
|
// No session exists in the database to update. This happens when we have called
|
||||||
|
// session_regenerate_id()
|
||||||
|
$this->createNewSession($id, $data);
|
||||||
|
}
|
||||||
|
} catch (\PDOException $e) {
|
||||||
|
throw new \RuntimeException(sprintf('PDOException was thrown when trying to manipulate session data: %s', $e->getMessage()), 0, $e);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new session with the given $id and $data
|
||||||
|
*
|
||||||
|
* @param string $id
|
||||||
|
* @param string $data
|
||||||
|
*/
|
||||||
|
private function createNewSession($id, $data = '')
|
||||||
|
{
|
||||||
|
$this->con->executeQuery("INSERT INTO {$this->tableName} (sess_id, sess_data, sess_time) VALUES (:id, :data, :time)", array(
|
||||||
|
'id' => $id,
|
||||||
|
'data' => $data,
|
||||||
|
'time' => time(),
|
||||||
|
));
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,39 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Symfony\Bridge\Doctrine\HttpFoundation;
|
||||||
|
|
||||||
|
use Doctrine\DBAL\Schema\Schema;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* DBAL Session Storage Schema.
|
||||||
|
*
|
||||||
|
* @author Johannes M. Schmitt <schmittjoh@gmail.com>
|
||||||
|
*/
|
||||||
|
final class DbalSessionStorageSchema extends Schema
|
||||||
|
{
|
||||||
|
private $tableName;
|
||||||
|
|
||||||
|
public function __construct($tableName = 'sessions')
|
||||||
|
{
|
||||||
|
parent::__construct();
|
||||||
|
|
||||||
|
$this->tableName = $tableName;
|
||||||
|
$this->addSessionTable();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function addToSchema(Schema $schema)
|
||||||
|
{
|
||||||
|
foreach ($this->getTables() as $table) {
|
||||||
|
$schema->_addTable($table);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private function addSessionTable()
|
||||||
|
{
|
||||||
|
$table = $this->createTable($this->tableName);
|
||||||
|
$table->addColumn('sess_id', 'string');
|
||||||
|
$table->addColumn('sess_data', 'text')->setNotNull(true);
|
||||||
|
$table->addColumn('sess_time', 'integer')->setNotNull(true)->setUnsigned(true);
|
||||||
|
$table->setPrimaryKey(array('sess_id'));
|
||||||
|
}
|
||||||
|
}
|
Reference in New Issue
Block a user