8 votes

Problèmes du gestionnaire de session personnalisé de PHP (PHP 7.1)

Je viens de migrer de PHP 7.0 à PHP 7.1 (installation propre de la version actuelle de WAMP) sur un ordinateur et il semble que quelque chose soit cassé dans le gestionnaire de session personnalisé qui est censé enregistrer la session dans la base de données au lieu d'utiliser le système de fichiers.

La classe de la main personnalisée est :

class db_session_handler implements SessionHandlerInterface {

public function __construct($db) {
    $this->db = $db;
}

public function open($save_path,$session_name) {
    $this->db;
    return true;
}

public function close() {
    unset($this->db);
    return true;
}

public function read($session_id) {

    if (!isset($session_id)) {
        $session_id='';
    }

    try {
        $sql="
            SELECT
                sess_data
            FROM
                ue_user_session
            WHERE
                sess_id = :sess_id
        ";
        $stmt = $this->db->prepare($sql);
        $stmt->bindParam(':sess_id', $session_id);
        $stmt->execute();
        $res = $stmt->fetchAll(PDO::FETCH_ASSOC);
        if (count($res) <> 1 ) {
            return false;
        } else {
            return $res[0]['sess_data'];
        }
    }
    catch (PDOException $e) {
        error_log('Error reading the session data table in the session reading method.',3,"C:\wamp\www\universal_empires\test_log.txt");
        error_log(" Query with error: $sql",3,"C:\wamp\www\universal_empires\test_log.txt");
        error_log(" Reason given: $e->getMessage()",3,"C:\wamp\www\universal_empires\test_log.txt");
        return false;
    }
}

public function write($session_id,$session_data) {

    try {
        $sql="
            SELECT
                sess_data
            FROM
                ue_user_session
            WHERE
                sess_id = :sess_id
        ";
        $stmt = $this->db->prepare($sql);
        $stmt->bindParam(':sess_id', $session_id);
        $stmt->execute();
        $res = $stmt->fetchAll(PDO::FETCH_ASSOC);

    }
    catch (PDOException $e) {
        error_log('Error reading the session data table in the session reading method.',3,"C:\wamp\www\universal_empires\test_log.txt");
        error_log(" Query with error: $sql",3,"C:\wamp\www\universal_empires\test_log.txt");
        error_log(" Reason given: $e->getMessage()",3,"C:\wamp\www\universal_empires\test_log.txt");
        return false;
    }
    $ip = get_ip();
    if (isset($_SESSION['user_id'])) {
        $user_id = (int) $_SESSION['user_id'];
    } else {
        $user_id= (int) 0;
    }       
    if (empty($res)) {

        if (!isset($_SERVER['REDIRECT_URL'])) {
            $location = 'Unknown';
        } else {
            $location = $_SERVER['REDIRECT_URL'];
        }

        try {
            if (count($res) === 0) {
                $sql="
                    INSERT INTO
                        ue_user_session
                    (
                          sess_id
                        , user
                        , start
                        , last_activity
                        , location
                        , ip
                        , user_agent
                        , user_host
                        , user_language
                        , expires
                        , sess_data
                    )
                    VALUES
                        (
                              :sess_id
                            , 0
                            , NOW()
                            , NOW()
                            , :location
                            , :ip
                            , :user_agent
                            , :user_host
                            , :user_lang
                            , DATE_ADD(NOW(), INTERVAL 30 MINUTE)
                            , :sess_data                        
                        )               
                ";

                $stmt = $this->db->prepare($sql);
                $stmt->bindParam(':sess_id', $session_id);
                $stmt->bindParam(':location', $location);
                $stmt->bindParam(':ip', $ip);
                $stmt->bindParam(':user_agent', $_SERVER['HTTP_USER_AGENT']);
                $stmt->bindParam(':user_host', $_SERVER['REMOTE_HOST']);
                $stmt->bindParam(':user_lang', $_SERVER['HTTP_ACCEPT_LANGUAGE']);
                $stmt->bindParam(':sess_data', $session_data);
                $stmt->execute();
                return true;
            }
        }
        catch (PDOException $e) {
            error_log('Error reading the session data table in the session reading method.',3,"C:\wamp\www\universal_empires\test_log.txt");
            error_log(" Query with error: $sql",3,"C:\wamp\www\universal_empires\test_log.txt");
            error_log(" Reason given: $e->getMessage()",3,"C:\wamp\www\universal_empires\test_log.txt");
            return false;
        }
    } else {

        try {
            $sql="
                UPDATE
                    ue_user
                SET
                    last_activity = NOW()
                WHERE
                    id =  :user_id
            ";
            $stmt = $this->db->prepare($sql);
            $stmt->bindParam(':user_id', $user_id);
            $stmt->execute();
        }
        catch (PDOException $e) {
            error_log('Error reading the session data table in the session reading method.',3,"C:\wamp\www\universal_empires\test_log.txt");
            error_log(" Query with error: $sql",3,"C:\wamp\www\universal_empires\test_log.txt");
            error_log(" Reason given: $e->getMessage()",3,"C:\wamp\www\universal_empires\test_log.txt");
            return false;
        }

        if (!isset($_SERVER['REDIRECT_URL'])) {
            $location = 'Unknown';
        } else {
            $location = $_SERVER['REDIRECT_URL'];
        }
        try {

            $sql="
                UPDATE
                    ue_user_session
                SET
                      last_activity = NOW()
                    , expires = DATE_ADD(NOW(), INTERVAL 30 MINUTE)
                    , location = :location
                    , ip = :ip
                    , user_agent = :user_agent
                    , user_host = :user_host
                    , user_language = :user_lang
                    , sess_data = :sess_data
                    , user = :user_id
                WHERE
                    sess_id = :sess_id              
            ";

            $stmt = $this->db->prepare($sql);
            $stmt->bindParam(':location', $location);
            $stmt->bindParam(':ip', $ip);
            $stmt->bindParam(':user_agent', $_SERVER['HTTP_USER_AGENT']);
            $stmt->bindParam(':user_host', $_SERVER['REMOTE_HOST']);
            $stmt->bindParam(':user_lang', $_SERVER['HTTP_ACCEPT_LANGUAGE']);
            $stmt->bindParam(':sess_data', $session_data);
            $stmt->bindParam(':user_id', $user_id);
            $stmt->bindParam(':sess_id', $session_id);
            $stmt->execute();
            return true;
            }
        catch (PDOException $e) {
            error_log('Error reading the session data table in the session reading method.',3,"C:\wamp\www\universal_empires\test_log.txt");
            error_log(" Query with error: $sql",3,"C:\wamp\www\universal_empires\test_log.txt");
            error_log(" Reason given: $e->getMessage()",3,"C:\wamp\www\universal_empires\test_log.txt");
            return false;
        }
    }
    $this->gc();
}

public function destroy($session_id) {
    try {
        $sql="
            DELETE FROM
                ue_user_session
            WHERE
                sess_id = :sess_id
        ";
        $stmt = $this->db->prepare($sql);
        $stmt->bindParam(':sess_id', $session_id);
        $stmt->execute();
        return true;
    }
    catch (PDOException $e) {
        error_log('Error reading the session data table in the session reading method.',3,"C:\wamp\www\universal_empires\test_log.txt");
        error_log(" Query with error: $sql",3,"C:\wamp\www\universal_empires\test_log.txt");
        error_log(" Reason given: $e->getMessage()",3,"C:\wamp\www\universal_empires\test_log.txt");
        return false;
    }
}

public function gc($max_lifetime) {
    try {
        $sql="
            DELETE FROM
                ue_user_session
            WHERE
                NOW() > expires
        ";
        $stmt = $this->db->prepare($sql);
        $stmt->execute();
        return true;
    }
    catch (PDOException $e) {
        error_log('Error reading the session data table in the session reading method.',3,"C:\wamp\www\universal_empires\test_log.txt");
        error_log(" Query with error: $sql",3,"C:\wamp\www\universal_empires\test_log.txt");
        error_log(" Reason given: $e->getMessage()",3,"C:\wamp\www\universal_empires\test_log.txt");
        return false;
    }
}

} ?>

Il est initié par : ini_set('session.use_only_cookies',1) ;

    $db_session_handler = new db_session_handler($db);
    session_set_save_handler($db_session_handler,true);

    if (session_start() === false ) {
        die('The Session Handler Is Broken!!!!');
    }

En lisant la page de manuel de session_set_save_handler(), je ne trouve rien qui puisse expliquer l'erreur que je reçois, à savoir.. :

Attention : session_start() : Échec de la lecture des données de session : user (chemin : c:/wamp/tmp) en C:\wamp\www\universal_empires\libs\bootstrap.php à la ligne 36

La ligne 36 de ce fichier est l'appel à session_start().

En cherchant un peu, les seules corrections que je peux trouver sont spécifiques à un cadre donné. Ce que j'ai besoin de savoir, c'est ce qui fait que session_start() échoue (d'après ce que j'ai lu sur les changements apportés à la version 7.1, session_start() renvoie false au lieu d'essayer de continuer quand quelque chose ne va pas.

Je pense que quelque chose a changé dans la version 7.1. Alors que dans la version 7.0, il était possible de continuer, la version 7.1 est plus stricte et renvoie session_start() false.

J'ai vidé la table des sessions dans la base de données et j'ai vérifié où les sessions basées sur des fichiers sont stockées. Le seul fichier de session "basé sur un fichier" présent est PHPMyAdmin.

Quelqu'un sait-il ce qu'il reproche à PHP 7.1 et qu'il ne reproche pas à PHP 7.0 ?

20voto

SpacePhoenix Points 381

Le coupable a été trouvé. Il s'avère que session_start() n'aime pas que la méthode read d'un gestionnaire de session personnalisé renvoie false s'il n'y a pas de session existante. Si quelqu'un d'autre rencontre un problème similaire, si vous n'avez pas de session existante, alors la méthode read doit retourner une chaîne vide au lieu de false ou null.

La solution a été trouvée à http://php.net/manual/en/function.session-start.php#120589 Je regardais la page du manuel de session_set_save_handler(), sans m'attendre à ce que la solution se trouve dans la section des commentaires de la page de session_start().

Je ne sais pas pourquoi la modification a été apportée à ce que la méthode session_start() attend de la méthode read d'un gestionnaire de session personnalisé.

0voto

Paul Points 1

En convertissant le panier d'achat d'interspire en php7.2, nous avons dû ajouter

return $session='';

à la ligne 98 de class.sessions.php. Cela a permis de se débarrasser de l'avertissement.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X