Incrementer tous les jours en PHP

Résolu
Bonjour, je voudrai établir un système de décrémenter le nombre des jours à partir d'une heure donnée(23:00pm),
Voici la partie de mon code concernée:


// Connexion dans la table time
try
    {		
 $req2 = $bdd->prepare('SELECT * FROM time WHERE id = ?');
	
	$req2->execute(array($_SESSION["id"]));
			 
	 }
    catch(Exception $e)
    {
        die('Erreur : '.$e->getMessage());
    }
$dom = $req2->fetch(); 	
			
$delai = $dom['duree']; $code = $dom['code'];	
			
		
$heure = date("g:i a");	

//Condition de décrémentation		 
	while($req2->fetch() ) {				
					
	if($delai != 0 ) {
		
	if ($heure == "23:00 pm") {
		
	$delai = $delai - 1;
		
	$sql = 'UPDATE time SET duree = ?   WHERE id = ?';
$datas = array($delai, $_SESSION["id"]);
try{
  $req = $bdd->prepare($sql);
  $req->execute($datas);  
} catch ( Exception $e ) {
    // en cas d'erreur :
    echo " Erreur ! " . $e->getMessage ();
    print_r ( $datas );
    exit;
  }		
		
$i =1;	
	while($heure != "23:01 pm" ) {	$i++; }// dès qu'il décrémente il fait une minute dans la boucle jusqu'à 23: 01 pm
		
		
	}
		
	$heure = date("g:i a");		

	 } 	
		
   } 


Le constat que j'ai fait c'est que mon code n'excute pas après l'heure prévu, le nombre de jour est le même, quelqu'un peut-il me dire ce qui coince avec mon code ? SVP

9 réponses

Résumé de la discussion

Un script PHP cherche à décrémenter quotidiennement le nombre de jours d'un abonnement à partir de 23:00, mais le décompte ne s'actualise pas comme prévu. Plusieurs remarques pointent que la condition horaire et la mise à jour de la variable d'heure ne se produisent pas correctement dans la boucle, empêchant le test '23:00 pm' de se déclencher. Des solutions consistent à enregistrer la date de début et/ou d'échéance et à calculer les jours restants via des différences de dates, plutôt que de diminuer un champ durée. En pratique, l'usage recommandé est de stocker au moins la date d'inscription ou d'échéance et de mettre à jour le décompte quotidiennement, idéalement via une vérification au login ou une tâche planifiée.

Bobot (l’IA à votre service)
  1. Contributeur
    bonjour,
    peux-tu rendre ton code plus lisible en respectant les conventions d'alignement?
    je suggère que tu ajoutes des echo pour que tu comprennes ce que fait ton code.
    ta boucle en ligne 43 me semble bizarre, la condition ne change jamais.
    0
    1. // Connexion dans la table time
      try
          {  
       $req2 = $bdd->prepare('SELECT * FROM time WHERE id = ?');
       
       $req2->execute(array($_SESSION["id"]));
          
        }
          catch(Exception $e)
          {
              die('Erreur : '.$e->getMessage());
          }
      $dom = $req2->fetch();  
         
      $delai = $dom['duree']; $code = $dom['code']; 
         
        
      $heure = date("g:i a"); 
      
      
      //Condition de décrémentation   
      while($req2->fetch() ) {    
      if($delai != 0 ) {
      if ($heure == "23:00 pm") {
        
      $delai = $delai - 1;
      $sql = 'UPDATE time SET duree = ?   WHERE id = ?';
      $datas = array($delai, $_SESSION["id"]);
      try{
        $req = $bdd->prepare($sql);
        $req->execute($datas);  
      } catch ( Exception $e ) {
          // en cas d'erreur :
          echo " Erreur ! " . $e->getMessage ();
          print_r ( $datas );
          exit;
        }  
       
      
       
      $i =1;
      // la boucle while est là pour faire passer 1min afin qu'il ne refasse plus le test de $heure == "23:00 pm" 
      while($heure != "23:01 pm" ) { $i++; }
      }
      $heure = date("g:i a");  
       }  
      }
      


      Jai séparé les instructions, j'espère que c'est plus comprehensible
      0
      1. @yg_beC'est fait exprès, c'est pour eviter que la condition
         if ($heure == "23:00 pm")
        s'exécute pendant les 1 minutes. Je bloque ma condition
         if ($heure == "23:00 pm")
        avec la boucle WHILE, pour que dès que ça sera 23:01 pm, il va sortir de
         if ($heure == "23:00 pm")
        et attendre la prochaine 23:01 pm, je sais pas si tu m'a compris?

        Ce que j'ai remarqué c'est que c'est comme si la condition
         if ($heure == "23:00 pm")
        s'execute pas
        0
      2. Contributeur
        @modemo2018as-tu ajouté des echo pour t'aider à comprendre ce que fait ton code?
        par exemple:
        echo $heure;
        avant le if de la ligne 24.
        0
      3. Contributeur
        @modemo2018la condition de la boucle while ne change pas dans la boucle: si tu y rentres, tu ne vas jamais en sortir.
        0
    2. Modérateur
      Bonjour,

      Si tu avais fait ce qu'Yg_be t'avait conseillé ( mettre des echo dans ton code pour essayer de comprendre ce qui ne fonctionne pas) et qu'en plus tu avais pris soin de bien lire ce qu'il t'a indiqué ( la condition ne change jamais.)
      . tu aurais pu constater que ta variable $heure, vu qu'elle se trouve en dehors de ta boucle .. ne change pas !
      Et donc.. que ta condition IF se basera TOUJOURS sur l'heure qu'il était lorsque tu as affiché ta page....

      0
      1. Oui tu as raison, le fait que la variable $heure soit dehors empêche l'execution de ma boucle comme j'aurai souhaité.
        Merci
        0
    3. Contributeur
      je pense que ton code est très loin de faire ce que tu souhaites.
      cependant, tu n'expliques pas ce que tu veux réaliser.
      0
      1. Modérateur
        Surtout qu'un script PHP a une certaine "durée" de vie.... et à moins de forcer le set_time_limit à une durée excessive ( à ne surtout pas faire !!! ) ... le script s'arrêtera avant d'avoir atteint l'heure souhaitée.
        0
      2. Contributeur
        si je devine ce que tu veux réaliser, il est préférable d'enregistrer des moments, pas des délais.
        0
    4. La variable delais contient le nombre de jours, le but de mon programme c'est que le nombre de jours se décrémente à une heure donnée, puis s'actualise dans la base de donnée, puis lorsqu'il arrive dans la boucle
      while($heure != "10:54 am" ) { $i++; } 
      il comptabilise le nombre de $i dans le but de faire passer le temps et ne plus exécuté
      if ($heure == "10:53 am")


      y
          {  
       $req2 = $bdd->prepare('SELECT * FROM time WHERE id = ?');
       
       $req2->execute(array($_SESSION["id"]));
          
        }
          catch(Exception $e)
          {
              die('Erreur : '.$e->getMessage());
          }
        
      //calcul delai  
      while($req2->fetch() ) {
      $heure = date("g:i a"); 
      
       $delai = $dom['duree'];  
        
       $heure = date("g:i a"); 
           
       if($delai != 0 ) {
        
       if ($heure == "10:53 am") {
        
       $delai = $delai - 1;
        
       $sql = 'UPDATE time SET duree = ?   WHERE id = ?';
      $datas = array($delai, $_SESSION["id"]);
      try{
        $req = $bdd->prepare($sql);
        $req->execute($datas);  
      } catch ( Exception $e ) {
          // en cas d'erreur :
          echo " Erreur ! " . $e->getMessage ();
          print_r ( $datas );
          exit;
        }  
        
      $i =1; 
       while($heure != "10:54 am" ) { $i++; }  
       echo $i ; 
       }
        } 
      
         } 
      
      


      J'ai mis la variable $heure à l'intérieur et je met les echo pour comprendre ce qui se passe dans la boucle, le onstat c'est qu' apparement la condition
       f ($heure == "10:53 am") 
      voilà pourquoi il n'ya pas décrémentation
      Quelqu'un peut-il m'aidé SVP?
      0
      1. Contributeur
        as-tu fait comme expliqué en #5?

        en tous cas, tu n'as pas change la boucle en ligne 40, la condition n'y change jamais.

        je pense que ton code est très loin de faire ce que tu souhaites.
        cependant, tu n'expliques pas ce que tu veux réaliser.
        0
    5. Oui j'ai ajouté un
       echo $heure;
      , s'affiche dans la boucle WHILE mais la condition IF ne s'exécute pas

      Comme j'ai expliqué précédemment, la ligne 40 est mis expressément, c'est pour que la condition
       if ($heure == "10:53 am")
      s'exécute qu'une seule fois, car dans de 10:53 à 10:54, il ya une minute qui s'écroule cela veut dire que la variable $delai va se décrémenter pendant une minute, hors la décrémentation doit se faire qu'une fois pas pendant une minutes d'où la présence de la ligne 40, qui sert à faire passé les 1 minutes
      J'espère que maintenant c'est plus comprehensible

      
      try
          {  
       $req2 = $bdd->prepare('SELECT * FROM time WHERE id = ?');
       
       $req2->execute(array($_SESSION["id"]));
          
        }
          catch(Exception $e)
          {
              die('Erreur : '.$e->getMessage());
          }
      
      
         
      //calcul delai  
      $heure = date("g:i a"); 
        echo $heure; 
         
       while($req2->fetch() ) {
        
       $delai = $dom['duree'];  
        
       $heure = date("g:i a"); 
            echo $heure;
           
       if($delai != 0 ) {
        
       if ($heure == "11:33 am") {
        
       $delai = $delai - 1;
        
       $sql = 'UPDATE time SET duree = ?   WHERE id = ?';
      $datas = array($delai, $_SESSION["id"]);
      try{
        $req = $bdd->prepare($sql);
        $req->execute($datas);  
      } catch ( Exception $e ) {
          // en cas d'erreur :
          echo " Erreur ! " . $e->getMessage ();
          print_r ( $datas );
          exit;
        }  
        
      $i =1; 
       while($heure != "11:34 am" ) { $i++; }
        
        
       }
        } 
        
       echo $i; 
        
         } 
      
      
      0
      1. Modérateur
        Il y a de gros soucis avec ton code.
        Comme déjà évoqué ... un script php ne peut fonctionner qu'un certain temps... ( en général, une vingtaine de secondes ).
        Pour quelques cas rares, on peut modifier cette "limite" ... mais il est préférable d'éviter.

        Ensuite, au moment où tu lances ton script ... quelle heure est-il exactement ?
        Car, si ce n'est pas pile poile 10h53 ... ça ne rentrera jamais dans ton if.

        A savoir également, qu'il est préférable d'utiliser les fonctions de manipulation des dates / times pour faire tes comparaisons...
        (tu les trouveras dans le manuel php et des exemples en pagaille sur le net )
        par exemple
        if (time() >= strtotime("11:33:00")) {
          echo "ok";
        }
        


        Pour finir, je pense que tu essais de faire un truc bancale avec ton code !
        Quel est le but de ce script ?
        Comment est-il lancé ?
        0
    6. Le but de mon script est d'établir un système de durée d'abonnement, c-à-d, lorsque l'abonné au compte s'enregistre pour la 1ère fois, il reçoit un délai de 30 jours, à compter de ce jour, le nombre de jour se décompte, en partant de 30 jusqu'à 0 jour, lorsque les 0 atteint l'abonné doit se réabonné sinon son compte est bloqué s'il ne renouvelle pas son abonnement

      C'est le système de décompte de jours que j'essai d'établir, c'est jusque je suis pas trop fort avec la manipulation des dates/times
      0
      1. Modérateur
        Je ne vois pas ce que viennent faire des boucles ici...
        A chaque rechargement de la page, il te suffit de comparer la date d'abonnement avec la date du jour.
        Si inférieur à 30... il a accès....
        Sinon... tu le rediriges vers la pages pour payer.

        Ce n'est pas plus compliqué que ça !

        Php s'exécute lors de l'appel à la page.
        Une fois la page chargée, php n'intervient plus..... donc ton histoire de boucle est inutile et stupide.

        Je pense qu'avant de coder, tu devrais déjà établir un cahier des charges de ce que tu veux faire puis faire un découpage fonctionnel en prenant le temps de bien réfléchir à l’algorithme à mettre en place et en te documentant sur ce qui est "faisable" ou non.
        Là tu pars un peu dans tous les sens en essayant de bidouiller ...
        0
      2. Contributeur
        @jordane45ou bien d'enregistrer la date de fin de l'abonnement dans la base de données.
        0
      3. Modérateur
        @yg_beDans ce cas, ça ne serait pas OU mais ET
        On conserve la date à laquelle l'utilisateur s'est abonné ( en cas d'éventuel litige...) ET on peut également stocker la date de fin de l'abonnement.
        0
      4. Contributeur
        @jordane45c'était une alternative à l'utilisation d'une période fixe de 30 jours, au moment de vérifier si l'abonnement est expiré.
        0
      5. Modérateur
        @yg_beOui, j'avais bien compris.
        C'est juste qu'il est préférable, dans tous les cas, de stocker AU MOINS la date d'inscription. ( au moins.. j'insiste).
        Et donc, qu'on peut aussi stocker la date ( déjà calculée ) de l'échéance.
        Je te reprenais juste sur le "ou" .. qu'il faudrait plutôt remplacer par "et" ....
        0
    7. Merci pour la suggestion de travailler avec la date d'abonnement, je me suis penché sur cette suggestion et j'ai conçu quelque chose
      Lorsque l'utilisateur se connecte, la date du jour est pris par
       $jour = date("Y-m-d");
      , lorsqu'il arrive à la page d'accueil, ainsi s'exécute ce programme

      $jour = !empty ( $_GET['date'] ) ? $_GET['date'] : NULL;    
         
      try
          {  
       $req2 = $bdd->prepare('SELECT * FROM time WHERE id = ?');
       $req2->execute(array($_SESSION["id"]));   
        }
          catch(Exception $e)
          {
              die('Erreur : '.$e->getMessage());
          }
      
       $dom =  $req2->fetch();
         
      //calcul delai  
       $delai = $dom['duree'];
       $date = $dom['date']; 
       echo $delai; 
      
      if( $jour != $date){  
       if($delai != 0 ) {  
        $diff = abs(strtotime($jour) - strtotime($date));
      $nbJours = $diff /86400; // conversion du calcul en jour (60x60x24)
        
       $delai = $delai - $nbJours;
        
       $sql = 'UPDATE time SET duree = ?   WHERE id = ?';
      $datas = array($delai, $_SESSION["id"]);
      try{
        $req = $bdd->prepare($sql);
        $req->execute($datas);  
      } catch ( Exception $e ) {
          // en cas d'erreur :
          echo " Erreur ! " . $e->getMessage ();
          print_r ( $datas );
          exit;
        }  
       }  
        } 
      
      echo' '; echo $nbJours; echo' '; echo $delai; // pour tester le resultat
      


      Ce programme est conçu par le principe où lorsque quelqu'un s'abonne il lui ai attribué un code qui correspond à certains nombre de jours bien connu, à chaque jour où il se connecte le nombre des jour lié à son code diminue en partant de
        $diff = abs(strtotime($jour) - strtotime($date));
      $nbJours = $diff /86400; // conversion du calcul en jour (60x60x24)
      d'où la soustraction
       $delai = $delai - $nbJours;
      après la BDD s'actualise

      Le constat fait c'est qu'après calcul il m'affiche des nombres negative, c'est comme si la conversion en jours du calcul
       $nbJours = $diff /86400;
      se passe pas bien et en plus c'est comme si il n'exécute pas la condition
      if( $jour != $date){


      En plus SVP comment faire pour que ce calcul s'effectue qu'une seule fois le jour? car à chaque fois que je me connecte il teste la boucle et effectue le calcul
      0
      1. Contributeur
        pourquoi n'enregistres-tu pas dans la base de données la date de la fin de l'abonnement?
        il deviendra alors inutile de faire toutes ces opérations.
        0
      2. @yg_beJ'ai appliqué la date de fin, ça marché, voici le code :

        $jour = !empty ( $_GET['date'] ) ? $_GET['date'] : NULL;			 
        		 
        try
            {		
         $req2 = $bdd->prepare('SELECT * FROM time WHERE id = ?');
        	
        	$req2->execute(array($_SESSION["id"]));
        			 
        	 }
            catch(Exception $e)
            {
                die('Erreur : '.$e->getMessage());
            }
        
         $dom =  $req2->fetch();
        			
        //calcul delai		
        
          
         $delai = $dom['duree'];
         
          $diff = abs(strtotime($delai) - strtotime($jour));
        $nbJours = $diff /86400;
        
        echo' '; echo $nbJours;
        


        En plus SVP comment faire pour que ce calcul s'effectue qu'une seule fois le jour? car à chaque fois que je me connecte il effectue le calcul, quel condition pourrai-je mettre par exemple pour qu'il fasse le calcul une seule fois?
        0
      3. @yg_beJ'ai appliqué la date de fin, ça marché, voici le code :

        $jour = !empty ( $_GET['date'] ) ? $_GET['date'] : NULL;    
           
        try
            {  
         $req2 = $bdd->prepare('SELECT * FROM time WHERE id = ?');
         
         $req2->execute(array($_SESSION["id"]));
            
          }
            catch(Exception $e)
            {
                die('Erreur : '.$e->getMessage());
            }
        
         $dom =  $req2->fetch();
           
        //calcul delai  
        
          
         $delai = $dom['duree'];
         
          $diff = abs(strtotime($delai) - strtotime($jour));
        $nbJours = $diff /86400;
        
        echo' '; echo $nbJours;
        


        Et plus SVP comment faire pour que ce calcul s'effectue qu'une seule fois le jour? car à chaque fois que je me connecte il effectue le calcul et m'affiche un nombre incoherent

        Quel condition pourrai-je mettre par exemple pour qu'il fasse le calcul une seule fois le jour?
        0
      4. Contributeur
        @modemo2018comme tu connais la date de fin, je ne vois plus de raison d'enregistrer, ni de mettre à jour le délai.
        0
      5. @yg_beIl ne met plus à jour ou enregistre une date quelconque le
        $diff = abs(strtotime($delai) - strtotime($jour));
        $nbJours = $diff /86400;  echo $nbJours;
         
        est mit pour faire connaitre à l'utilisateur le nombre de jour qui lui reste de sa validité, car à une semaine du délai butoir il reçoit le message d'alert

        comment faire pour que ce calcul s'effectue qu'une seule fois le jour? car à chaque fois que je me connecte il effectue le calcul et m'affiche un nombre incoherent

        Quel condition pourrai-je mettre par exemple pour qu'il fasse le calcul une seule fois le jour?
        0
    8. exactement c'est inutile, j'enregistre pas le nombre de jours restant, en ce qui concerne ce problème je l'ai déjà résolu par ta proposition, mon programme enregistre juste la date de debut et la date de fin d'abonnement, mais je donne la possibilité à l'abonnée de connaitre le nombre des jours qui lui reste en affichant sur mon site celui-ci d'où :

        $diff = abs(strtotime($delai) - strtotime($jour));
      $nbJours = $diff /86400;
      
      echo' '; echo $nbJours;
      
      


      Donc lorsque l'abonné se connecte, la date du jour est récupéré puis fait la soustraction avec la date de fin, ainsi le nombre de jours restant lui est affiché
      Le problème que j'ai actuellement c'est que lorsque l'abonné se connecte pour la première fois(en un jour) mon code s'execute normalement et affiche le bon le nombre,
      mais une fois deconnecté puis se reconnecte, il affiche un resultat incoherent, je ne comprend pas pourquoi il agit comme ça
      0
      1. Contributeur
        difficile de comprendre ce que tu fais quand tu ne montres qu'une petite partie de ton code.
        tu ne donnes pas d'information précise à propos de ce qu'il affiche.
        as-tu affiché les valeurs de $delai, $jour, $nbjours et $diff? cela t'aidera à déterminer d'où vient l'erreur.
        0
      2. @yg_beEureka!! j'ai résolu le problème, j'ai pu répéré mon erreur, c'est réglé. GRAND MERCI
        0