You are here

private function PdoSessionHandler::doRead in Zircon Profile 8.0

Same name and namespace in other branches
  1. 8 vendor/symfony/http-foundation/Session/Storage/Handler/PdoSessionHandler.php \Symfony\Component\HttpFoundation\Session\Storage\Handler\PdoSessionHandler::doRead()

Reads the session data in respect to the different locking strategies.

We need to make sure we do not return session data that is already considered garbage according to the session.gc_maxlifetime setting because gc() is called after read() and only sometimes.

Parameters

string $sessionId Session ID:

Return value

string The session data

1 call to PdoSessionHandler::doRead()
PdoSessionHandler::read in vendor/symfony/http-foundation/Session/Storage/Handler/PdoSessionHandler.php

File

vendor/symfony/http-foundation/Session/Storage/Handler/PdoSessionHandler.php, line 502

Class

PdoSessionHandler
Session handler using a PDO connection to read and write data.

Namespace

Symfony\Component\HttpFoundation\Session\Storage\Handler

Code

private function doRead($sessionId) {
  $this->sessionExpired = false;
  if (self::LOCK_ADVISORY === $this->lockMode) {
    $this->unlockStatements[] = $this
      ->doAdvisoryLock($sessionId);
  }
  $selectSql = $this
    ->getSelectSql();
  $selectStmt = $this->pdo
    ->prepare($selectSql);
  $selectStmt
    ->bindParam(':id', $sessionId, \PDO::PARAM_STR);
  $selectStmt
    ->execute();
  $sessionRows = $selectStmt
    ->fetchAll(\PDO::FETCH_NUM);
  if ($sessionRows) {
    if ($sessionRows[0][1] + $sessionRows[0][2] < time()) {
      $this->sessionExpired = true;
      return '';
    }
    return is_resource($sessionRows[0][0]) ? stream_get_contents($sessionRows[0][0]) : $sessionRows[0][0];
  }
  if (self::LOCK_TRANSACTIONAL === $this->lockMode && 'sqlite' !== $this->driver) {

    // Exclusive-reading of non-existent rows does not block, so we need to do an insert to block
    // until other connections to the session are committed.
    try {
      $insertStmt = $this->pdo
        ->prepare("INSERT INTO {$this->table} ({$this->idCol}, {$this->dataCol}, {$this->lifetimeCol}, {$this->timeCol}) VALUES (:id, :data, :lifetime, :time)");
      $insertStmt
        ->bindParam(':id', $sessionId, \PDO::PARAM_STR);
      $insertStmt
        ->bindValue(':data', '', \PDO::PARAM_LOB);
      $insertStmt
        ->bindValue(':lifetime', 0, \PDO::PARAM_INT);
      $insertStmt
        ->bindValue(':time', time(), \PDO::PARAM_INT);
      $insertStmt
        ->execute();
    } catch (\PDOException $e) {

      // Catch duplicate key error because other connection created the session already.
      // It would only not be the case when the other connection destroyed the session.
      if (0 === strpos($e
        ->getCode(), '23')) {

        // Retrieve finished session data written by concurrent connection. SELECT
        // FOR UPDATE is necessary to avoid deadlock of connection that starts reading
        // before we write (transform intention to real lock).
        $selectStmt
          ->execute();
        $sessionRows = $selectStmt
          ->fetchAll(\PDO::FETCH_NUM);
        if ($sessionRows) {
          return is_resource($sessionRows[0][0]) ? stream_get_contents($sessionRows[0][0]) : $sessionRows[0][0];
        }
        return '';
      }
      throw $e;
    }
  }
  return '';
}