Problème de session PHP

a marqué ce sujet comme résolu.

Bonjour,

Voila je rencontre un petit problème avec mon code. Je cherche à créer un système d’alerte par une sessions que j’appelle flash afin d’avertir l’utilisateur de : 1. Un mail à été envoyé pour confirmer le compte. 2. Que la clef de validation est invalide si c’est le cas

Une technique assez simple :

Si jamais le compte est créé, je créé une session flash :

$_SESSION['flash']['succes'] = "Un mail de confirmation vous a été envoyé!";

Si jamais une session flash existe, je l’affiche sur mon site.

Le petit message "flash" comme quoi la clef est invalide fonctionne mais pas le petit message pour la confirmation du compte.

Mon register :

    
     <?php session_start(); ?>
     <?php require 'inc/functions.php'; ?>
     <?php require 'inc/db.php'; ?>

     <?php

     if(!empty($_POST)) {


      $errors = array();

      // Vérifions que le Pseudo est valide.

       if(empty($_POST{'username'}) || !preg_match('/^[a-zA-Z0-9_]+$/', $_POST['username'])){
         $errors['username'] = "Votre pseudo n'est pas valide."; 
       } else // Vérifions que le pseudo n'est pas déjà utilisé.
           {
         $req = $pdo->prepare('SELECT id FROM users WHERE username = ?');
         $req->execute([$_POST['username']]);
         $user = $req->fetch();
         if($user) {
            $errors['username'] = 'Ce pseudo est déjà pris';
         }
       }

       // Vérifions que l'email est valide. 

       if(empty($_POST['email']) || !filter_var($_POST['email'], FILTER_VALIDATE_EMAIL)) {
         $errors['email'] = "Votre email n'est pas valide."; 
       } // Vérifions que l'email est valide.
       else {
         $req = $pdo->prepare('SELECT id FROM users WHERE email = ?');
         $req->execute([$_POST['email']]);
         $user = $req->fetch();
         if($user) {
            $errors['email'] = 'Cet email est déjà pris';
         }
       }

       if(empty($_POST['password']) || $_POST['password'] != $_POST['password_confirm']) {
         $errors['password'] = "Votre mot de passe est incorrect."; 
       }



       if(empty($errors)) {

       $req = $pdo->prepare("INSERT INTO users SET username = ?, password = ?, email = ?, confirmation_token = ?");

       $password = password_hash($_POST['password'], PASSWORD_BCRYPT);
       $token = str_random(60);
      
       $req->execute([$_POST['username'], $password, $_POST['email'], $token]);

       $user_id = $pdo->lastInsertId();



       mail($_POST['email'], "Confirmation de votre email', 'Pour valider ton compte clique sur ce lien : \n\n http://localhost/Bug/confirm.php?id=$user_id&token=$token");
    
        $_SESSION['flash']['succes'] = "Un mail de confirmation vous a été envoyé!"; 
       

       header('Location: login.php');
      

       }


     }

     ?>

Ma page de confirmation :

<?php

     $user_id = $_GET['id'];
     $token = $_GET['token'];

     require 'inc/db.php';

     $req = $pdo->prepare('SELECT * FROM users WHERE id = ?');
     $req->execute([$user_id]);

     $user = $req->fetch(); 
     session_start();

     if($user && $user->confirmation_token == $token){

      

      $req = $pdo->prepare('UPDATE users SET confirmation_token = NULL, confirmated_at = NOW() WHERE id = ?')->execute([$user_id]);

      $_SESSION['auth'] = $user;
      header('Location: account.php');


     } else {
      $_SESSION['flash']['danger'] = "Ce token n'est plus valide"; 
      header('Location: login.php');
     }

Ma page de login :

     <?php require 'inc/functions.php'; ?>
     <?php require 'inc/db.php'; ?>
     <?php session_start(); ?>
    


       <!--  Header -->
     <?php require 'inc/header.php'; ?>
     <!-- end Header -->


   
     <h1> Espace membre </h1>



      <!--  footer -->
      <?php require 'inc/footer.php'; ?>
      <!-- end footer -->

   </body>
</html>

mon header : (la partie concernée du header par ce message d’alerte)

      <?php if(isset($_SESSION['flash'])): ?>
         <?php foreach ($_SESSION['flash'] as $type => $message): ?>
           
           <div class ="alert alert-<?= $type; ?>"> <?= $message; ?></div>

         <?php endforeach; ?>
          <?php unset($_SESSION['flash']); ?> 
      <?php endif; ?>

Le message d’alerte "Flash" concernant l’invalidité du token fonctionne correctement, pas le message "Flash" concernant l’envoie d’une clef de confirmation. En définitif, la variable $_SESSION['flash'] est vide quand elle vient de register.php mais pas quand elle vient de confirm.php vers login.php Merci pour votre aide!

Salut !

Est-ce que ça pourrait venir de ce que ta requête d’insertion a une drôle de syntaxe, mélange de INSERT et de UPDATE, ce qui cause une erreur que tu ne vois pas du fait de la redirection (et que peut-être tu n’as pas activé l’affichage des erreurs MySQL) ?

+0 -0

Salut !

Est-ce que ça pourrait venir de ce que ta requête d’insertion a une drôle de syntaxe, mélange de INSERT et de UPDATE, ce qui cause une erreur que tu ne vois pas du fait de la redirection (et que peut-être tu n’as pas activé l’affichage des erreurs MySQL) ?

Ymox

Salut! Merci pour ta réponse! La requête SQL fonctionne parfaitement, tout est enregistré dans la base de donnée sans aucun soucis ni aucune erreur.

(Au cas où, j’ai fais un test, j’ai enlevé la requête SQL du code. Même sans cette requête la session ne passe pas entre register.php et login.php)

Donc le problème ne doit pas venir d’ici :/

Merci à toi!

Tu as essayé de faire un dd($_SESSION) après avoir écrit dedans et avant de les lire, pour vérifier que les données sont bien enregistrées ?

viki53

Salut, merci de ta réponse. Yep! La variable$_SESSION['flash']['succes'] n’existe tout simplement plus sur le fichier login.php après mon header location: login.php depuis mon register.php où je déclare cette fameuse variable $_SESSION['flash']['succes']. La variable ne passe pas entre les deux pages pourtant toutes les requêtes dans la boucle concernée par la création de cette variable sont exécutées.

Si je l’enlève la redirection vers logion.php et que j’affiche la variable avec un echo sur la page, elle est affichée. Donc la variable est bien crée, le problème ne vient pas là. Elle ne circule pas entre les pages. Je désespère et je suis certains que la raison est débile, c’est frustrant.

+0 -0

Je vois que tu fais ton session_start() plus tard sur la page login que sur ta page register… si tu remontes la ligne ça donne quoi ?

Sinon tu as vérifié que tu n’as pas d’autre redirection parasite (en regardant les flux réseaux dans ton navigateur) ?

viki53

J’ai remonté le session_start(), bougé 4–5 fois de position, rien ne change. J’ai tenté avec plusieurs navigateurs, rien ne change. Mystère.

Je ne pense pas qu’il faille regarder la page login.php puisque elle capable d’afficher la $_SESSION['flash'] provenant de confirm.php mais pas de register.php Il y a une donc une différence dans le code entre confirm.php et register.php qui empêche ce fonctionnement. Tout se passe parfaitement depuis confirm.php mais pas depuis register.php. La solution n’est pas en mon sens à aller chercher vers le login.php qui rempli parfaitement son rôle, le problème vient de register.php qui est incapable de transmettre cette session.

De plus, dans la boucle dans laquelle est cfée cette fameuse $_SESSION['flash'], l’ensemble des requêtes sont exécutées. La variable est donc crée mais ne transite pas.

Merci à toi !

Sur register.php fais attention aux ouvertures/fermetures de balises PHP, car ça risque d’envoyer des infos avant les headers.

Tu peux nous poster les fichiers mis au propre et à jour, avec leurs noms ?

viki53

Alors, il y a 4 fichiers concernés par ces sessions. 1. Le header.php qui affiche le fameux message @_SESSION['flash'] s’il existe. Ce fichier est incorporé dans le login.php et dans le register.php 2. le login.php dont fait partie le header.php où l’utilisateur peut voir ce message par le biais de l’incorporation du header.php 3. Le register.php où l’utilisateur s’inscrit, PHP inscrit l’utilisateur et créé un message @_SESSION['flash'] pour dire qu’un mail est envoyé pour confirmer le compte. C’est cette fameuse session qui est censée s’afficher mais qui transite pas vers header.php et login.php 4. Le confirm.php qui sert de page de confirmation du compte, il renvoi à login.php un message $_SESSION['flash'] pour dire que le compte est vérifié. Là, tout fonctionne, la session circule parfaitement.

Header.php (partie concernée, le reste n’est que du HTML)

      <?php if(isset($_SESSION['flash'])): ?>
         <?php foreach ($_SESSION['flash'] as $type => $message): ?>
           
           <div class ="alert alert-<?= $type; ?>"> <?= $message; ?></div>

         <?php endforeach; ?>
          <?php unset($_SESSION['flash']); ?> 
      <?php endif; ?>

login.php

     <?php require 'inc/functions.php'; ?>
     <?php require 'inc/db.php'; ?>
     <?php session_start(); ?>
    


       <!--  Header -->
     <?php require 'inc/header.php'; ?>
     <!-- end Header -->


   
     <h1> Espace membre </h1>



      <!--  footer -->
      <?php require 'inc/footer.php'; ?>
      <!-- end footer -->

   </body>
</html>

register.php (en mon sens, le centre du problème, incapable de transmettre la session)

     <?php require 'inc/functions.php'; ?>
     <?php require 'inc/db.php'; ?>*
      <?php session_start(); ?>

     <?php

     if(!empty($_POST)) {


      $errors = array();

      // Vérifions que le Pseudo est valide.

       if(empty($_POST{'username'}) || !preg_match('/^[a-zA-Z0-9_]+$/', $_POST['username'])){
         $errors['username'] = "Votre pseudo n'est pas valide."; 
       } else // Vérifions que le pseudo n'est pas déjà utilisé.
           {
         $req = $pdo->prepare('SELECT id FROM users WHERE username = ?');
         $req->execute([$_POST['username']]);
         $user = $req->fetch();
         if($user) {
            $errors['username'] = 'Ce pseudo est déjà pris';
         }
       }

       // Vérifions que l'email est valide. 

       if(empty($_POST['email']) || !filter_var($_POST['email'], FILTER_VALIDATE_EMAIL)) {
         $errors['email'] = "Votre email n'est pas valide."; 
       } // Vérifions que l'email est valide.
       else {
         $req = $pdo->prepare('SELECT id FROM users WHERE email = ?');
         $req->execute([$_POST['email']]);
         $user = $req->fetch();
         if($user) {
            $errors['email'] = 'Cet email est déjà pris';
         }
       }

       if(empty($_POST['password']) || $_POST['password'] != $_POST['password_confirm']) {
         $errors['password'] = "Votre mot de passe est incorrect."; 
       }



       if(empty($errors)) {

       $req = $pdo->prepare("INSERT INTO users SET username = ?, password = ?, email = ?, confirmation_token = ?");

       $password = password_hash($_POST['password'], PASSWORD_BCRYPT);
       $token = str_random(60);
      
       $req->execute([$_POST['username'], $password, $_POST['email'], $token]);

       $user_id = $pdo->lastInsertId();



       mail($_POST['email'], "Confirmation de votre email', 'Pour valider ton compte clique sur ce lien : \n\n http://localhost/Bug/confirm.php?id=$user_id&token=$token");


        $_SESSION['flash']['succes'] = "Un mail de confirmation vous a été envoyé!"; 



       header('Location: login.php');
      

       }


     }

     ?>
       <!--  Header -->
     <?php require 'inc/header.php'; ?>
     <!-- end Header -->


     <p> Inscription </p>

     <form action="" method="POST">

      <div class="form-group">
         <label for="">Pseudo</label>
         <input type="text" name="username" class="form-control"/>
      </div>

      <div class="form-group">
         <label for="">Email</label>
         <input type="email" name="email" class="form-control" />
      </div>

       <div class="form-group">
         <label for="">Mot de passe</label>
         <input type="password" name="password" class="form-control"/>
      </div>


       <div class="form-group">
         <label for="">Confirmation de votre mot de passe</label>
         <input type="password" name="password_confirm" class="form-control"/>
      </div>

      <button type="submit" class="btn btn-primary">M'inscrire</button>



     </form>

     <?php if(!empty($errors)): ?>

         <?php foreach($errors as $error): ?>
            <div class="alert alert-danger">
         <ul>
            <li> <?= $error; ?> </li>
      </div>
      </ul>
         <?php endforeach; ?>
      
      <?php endif; ?>

      




      <!--  footer -->
      <?php require 'inc/footer.php'; ?>
      <!-- end footer -->

   </body>
</html>

confirm.php (lui, capable de transmettre la session)

     <?php

     $user_id = $_GET['id'];
     $token = $_GET['token'];

     require 'inc/db.php';

     $req = $pdo->prepare('SELECT * FROM users WHERE id = ?');
     $req->execute([$user_id]);

     $user = $req->fetch(); 
     session_start();

     if($user && $user->confirmation_token == $token){

      

      $req = $pdo->prepare('UPDATE users SET confirmation_token = NULL, confirmated_at = NOW() WHERE id = ?')->execute([$user_id]);

      $_SESSION['auth'] = $user;
      $_SESSION['flash']['succes'] = "Bienvenue chez BUG!"; 
      header('Location: login.php');


     } else {
      $_SESSION['flash']['danger'] = "Ce token n'est plus valide"; 
      header('Location: login.php');
     }

Merci pour le temps que tu prend pour ce problème!

Ah mais voilà !

Dans register.php une fois que t’as envoyé un header de redirection, ton PHP s’arrête pas, donc il inclue et exécute header.php… donc vide tes données flash.

Quand tu fais une redirection il vaut mieux stopper l’exécution du script php juste après, par exemple avec die().

viki53

Wah, merci! Ca fonctionne! Je prend note du die(); pour mes prochaines redirections!

Merci :) !

Connectez-vous pour pouvoir poster un message.
Connexion

Pas encore membre ?

Créez un compte en une minute pour profiter pleinement de toutes les fonctionnalités de Zeste de Savoir. Ici, tout est gratuit et sans publicité.
Créer un compte