Session/Storage/Handler/PdoSessionHandler.php
public function write($sessionId, $data)
    {
        $data = base64_encode($data);

        $maxlifetime = (int) ini_get('session.gc_maxlifetime');

        try {
            // We use a single MERGE SQL query when supported by the database.
            $mergeSql = $this->getMergeSql();

            if (null !== $mergeSql) {
                $mergeStmt = $this->pdo->prepare($mergeSql);
                if ('sqlsrv' === $this->driver || 'oci' === $this->driver) {
                    $mergeStmt->bindParam(1, $sessionId, \PDO::PARAM_STR);
                    $mergeStmt->bindParam(2, $sessionId, \PDO::PARAM_STR);
                    $mergeStmt->bindParam(3, $data, \PDO::PARAM_LOB);
                    $mergeStmt->bindParam(4, $maxlifetime, \PDO::PARAM_INT);
                    $mergeStmt->bindValue(5, time(), \PDO::PARAM_INT);
                    $mergeStmt->bindParam(6, $data, \PDO::PARAM_LOB);
                    $mergeStmt->bindParam(7, $maxlifetime, \PDO::PARAM_INT);
                    $mergeStmt->bindValue(8, time(), \PDO::PARAM_INT);
                }
                else {
                    $mergeStmt->bindParam(':id', $sessionId, \PDO::PARAM_STR);
                    $mergeStmt->bindParam(':data', $data, \PDO::PARAM_LOB);
                    $mergeStmt->bindParam(':lifetime', $maxlifetime, \PDO::PARAM_INT);
                    $mergeStmt->bindValue(':time', time(), \PDO::PARAM_INT);
                }
                $mergeStmt->execute();
                return true;
            }

            $updateStmt = $this->pdo->prepare(
                "UPDATE $this->table SET $this->dataCol = :data, $this->lifetimeCol = :lifetime, $this->timeCol = :time WHERE $this->idCol = :id"
            );
            $updateStmt->bindParam(':id', $sessionId, \PDO::PARAM_STR);
            $updateStmt->bindParam(':data', $data, \PDO::PARAM_LOB);
            $updateStmt->bindParam(':lifetime', $maxlifetime, \PDO::PARAM_INT);
            $updateStmt->bindValue(':time', time(), \PDO::PARAM_INT);
            $updateStmt->execute();

            // When MERGE is not supported, like in Postgres, we have to use this approach that can result in
            // duplicate key errors when the same session is written simultaneously (given the LOCK_NONE behavior).
            // We can just catch such an error and re-execute the update. This is similar to a serializable
            // transaction with retry logic on serialization failures but without the overhead and without possible
            // false positives due to longer gap locking.
            if (!$updateStmt->rowCount()) {
                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->bindParam(':data', $data, \PDO::PARAM_LOB);
                    $insertStmt->bindParam(':lifetime', $maxlifetime, \PDO::PARAM_INT);
                    $insertStmt->bindValue(':time', time(), \PDO::PARAM_INT);
                    $insertStmt->execute();
                } catch (\PDOException $e) {
                    // Handle integrity violation SQLSTATE 23000 (or a subclass like 23505 in Postgres) for duplicate keys
                    if (0 === strpos($e->getCode(), '23')) {
                        $updateStmt->execute();
                    } else {
                        throw $e;
                    }
                }
            }
        } catch (\PDOException $e) {
            $this->rollback();

            throw $e;
        }

        return true;
    }
public function write($sessionId, $data)
    {
        $data = base64_encode($data);

        $maxlifetime = (int) ini_get('session.gc_maxlifetime');

        try {
            // We use a single MERGE SQL query when supported by the database.
            $mergeSql = $this->getMergeSql();

            if (null !== $mergeSql) {
                $mergeStmt = $this->pdo->prepare($mergeSql);
                if ('sqlsrv' === $this->driver || 'oci' === $this->driver) {
                    $mergeStmt->bindParam(1, $sessionId, \PDO::PARAM_STR);
                    $mergeStmt->bindParam(2, $sessionId, \PDO::PARAM_STR);
                    $mergeStmt->bindParam(3, $data, \PDO::PARAM_LOB);
                    $mergeStmt->bindParam(4, $maxlifetime, \PDO::PARAM_INT);
                    $mergeStmt->bindValue(5, time(), \PDO::PARAM_INT);
                    $mergeStmt->bindParam(6, $data, \PDO::PARAM_LOB);
                    $mergeStmt->bindParam(7, $maxlifetime, \PDO::PARAM_INT);
                    $mergeStmt->bindValue(8, time(), \PDO::PARAM_INT);
                }
                else {
                    $mergeStmt->bindParam(':id', $sessionId, \PDO::PARAM_STR);
                    $mergeStmt->bindParam(':data', $data, \PDO::PARAM_LOB);
                    $mergeStmt->bindParam(':lifetime', $maxlifetime, \PDO::PARAM_INT);
                    $mergeStmt->bindValue(':time', time(), \PDO::PARAM_INT);
                }
                $mergeStmt->execute();
                return true;
            }

            $updateStmt = $this->pdo->prepare(
                "UPDATE $this->table SET $this->dataCol = :data, $this->lifetimeCol = :lifetime, $this->timeCol = :time WHERE $this->idCol = :id"
            );
            $updateStmt->bindParam(':id', $sessionId, \PDO::PARAM_STR);
            $updateStmt->bindParam(':data', $data, \PDO::PARAM_LOB);
            $updateStmt->bindParam(':lifetime', $maxlifetime, \PDO::PARAM_INT);
            $updateStmt->bindValue(':time', time(), \PDO::PARAM_INT);
            $updateStmt->execute();

            // When MERGE is not supported, like in Postgres, we have to use this approach that can result in
            // duplicate key errors when the same session is written simultaneously (given the LOCK_NONE behavior).
            // We can just catch such an error and re-execute the update. This is similar to a serializable
            // transaction with retry logic on serialization failures but without the overhead and without possible
            // false positives due to longer gap locking.
            if (!$updateStmt->rowCount()) {
                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->bindParam(':data', $data, \PDO::PARAM_LOB);
                    $insertStmt->bindParam(':lifetime', $maxlifetime, \PDO::PARAM_INT);
                    $insertStmt->bindValue(':time', time(), \PDO::PARAM_INT);
                    $insertStmt->execute();
                } catch (\PDOException $e) {
                    // Handle integrity violation SQLSTATE 23000 (or a subclass like 23505 in Postgres) for duplicate keys
                    if (0 === strpos($e->getCode(), '23')) {
                        $updateStmt->execute();
                    } else {
                        throw $e;
                    }
                }
            }
        } catch (\PDOException $e) {
            $this->rollback();

            throw $e;
        }

        return true;
    }
public function write ( $ sessionId , $ data ) { $ data = base64_encode ( $ data ) ; $ maxlifetime = ( int ) ini_get ( 'session.gc_maxlifetime' ) ; try { // We use a single MERGE SQL query when supported by the database. $ mergeSql = $ this -> getMergeSql ( ) ; if ( null !== $ mergeSql ) { $ mergeStmt = $ this -> pdo -> prepare ( $ mergeSql ) ; if ( 'sqlsrv' === $ this -> driver || 'oci' === $ this -> driver ) { $ mergeStmt -> bindParam ( 1 , $ sessionId , \ PDO :: PARAM_STR ) ; $ mergeStmt -> bindParam ( 2 , $ sessionId , \ PDO :: PARAM_STR ) ; $ mergeStmt -> bindParam ( 3 , $ data , \ PDO :: PARAM_LOB ) ; $ mergeStmt -> bindParam ( 4 , $ maxlifetime , \ PDO :: PARAM_INT ) ; $ mergeStmt -> bindValue ( 5 , time ( ) , \ PDO :: PARAM_INT ) ; $ mergeStmt -> bindParam ( 6 , $ data , \ PDO :: PARAM_LOB ) ; $ mergeStmt -> bindParam ( 7 , $ maxlifetime , \ PDO :: PARAM_INT ) ; $ mergeStmt -> bindValue ( 8 , time ( ) , \ PDO :: PARAM_INT ) ; } else { $ mergeStmt -> bindParam ( ':id' , $ sessionId , \ PDO :: PARAM_STR ) ; $ mergeStmt -> bindParam ( ':data' , $ data , \ PDO :: PARAM_LOB ) ; $ mergeStmt -> bindParam ( ':lifetime' , $ maxlifetime , \ PDO :: PARAM_INT ) ; $ mergeStmt -> bindValue ( ':time' , time ( ) , \ PDO :: PARAM_INT ) ; } $ mergeStmt -> execute ( ) ; return true ; } $ updateStmt = $ this -> pdo -> prepare ( "UPDATE $this->table SET $this->dataCol = :data, $this->lifetimeCol = :lifetime, $this->timeCol = :time WHERE $this->idCol = :id" ) ; $ updateStmt -> bindParam ( ':id' , $ sessionId , \ PDO :: PARAM_STR ) ; $ updateStmt -> bindParam ( ':data' , $ data , \ PDO :: PARAM_LOB ) ; $ updateStmt -> bindParam ( ':lifetime' , $ maxlifetime , \ PDO :: PARAM_INT ) ; $ updateStmt -> bindValue ( ':time' , time ( ) , \ PDO :: PARAM_INT ) ; $ updateStmt -> execute ( ) ; // When MERGE is not supported, like in Postgres, we have to use this approach that can result in // duplicate key errors when the same session is written simultaneously (given the LOCK_NONE behavior). // We can just catch such an error and re-execute the update. This is similar to a serializable // transaction with retry logic on serialization failures but without the overhead and without possible // false positives due to longer gap locking. if ( ! $ updateStmt -> rowCount ( ) ) { 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 -> bindParam ( ':data' , $ data , \ PDO :: PARAM_LOB ) ; $ insertStmt -> bindParam ( ':lifetime' , $ maxlifetime , \ PDO :: PARAM_INT ) ; $ insertStmt -> bindValue ( ':time' , time ( ) , \ PDO :: PARAM_INT ) ; $ insertStmt -> execute ( ) ; } catch ( \ PDOException $ e ) { // Handle integrity violation SQLSTATE 23000 (or a subclass like 23505 in Postgres) for duplicate keys if ( 0 === strpos ( $ e -> getCode ( ) , '23' ) ) { $ updateStmt -> execute ( ) ; } else { throw $ e ; } } } } catch ( \ PDOException $ e ) { $ this -> rollback ( ) ; throw $ e ; } return true ; }
{@inheritdoc}
{