PHP 7 et @lex Guestbook

Vos idées et demandes pour la prochaine mise à jour du script sont les bienvenues ici - Your ideas and suggestions for the next update.

Modérateurs : boulmontjj, Pierre G., Malabar, Otomatic

Otomatic
Modérateur
Modérateur
Messages : 650
Inscription : Ven 11 Août 2006, 09:33
Localisation : Paris
Contact :

PHP 7 et @lex Guestbook

Messagepar Otomatic » Mar 09 Fév 2016, 11:24

Bonjour,

PHP 7 signe la disparition de MySQL, non pas du gestionnaire de base de données, mais de l'extension mysql.
Il faut donc impérativement utiliser les extensions mysqli ou PDO mysql à la place.
PDO mysql je connais un peu, mais pas trop, alors que mysqli présente beaucoup d'analogies avec mysql.
PHP 7 signe aussi l'obsolescence de l'utilisation du nom d'une class comme nom de la fonction constructeur de ladite class.

Donc, à la condition que toutes les autres modifications déjà préconisées pour PHP 5.4, 5.5 et 5.6 ainsi que le passage en utf-8 aient été réalisées, voici les modifications à effectuer pour PHP 7.

Je tiens à signaler que j'écris cette procédure à posteriori et que je peux oublier une modification effectuée.

La première chose à faire est de passer à mysqli et tant qu'à faire, autant aussi améliorer les choses, comme pouvoir voir, en mode debug, toutes les requêtes ainsi que leur temps d'exécution ; pourquoi ? Simplement parce que c'est quelque chose que j'utilise de base sur mes sites et que je n'ai pas eu à réinventer l'eau tiède.
Commençont par créer quelques fonctions supplémentaires pour MySQLi.
Créer un fichier (utf-8) agb\db\mysql_functions.php qui doit contenir :

Code : Tout sélectionner

<?php
//Fonctions générales
//Affiche les requêtes
function see_saved_queries() {
  global $f_db_connexion;
  $saved_queries = $f_db_connexion->get_saved_queries();
  $nb_queries = count($saved_queries);
  echo "<div id='sql_requete'>\n";
  if($nb_queries > 0) {
    echo "<table summary='Queries list'>\n";
    echo "<caption>Queries to database</caption>\n";
    echo "<tr><th>N°</th><th>Duration&nbsp;(s)</th><th style='width-min:500px;'>Queries ".TYPE_BASE_ALEX."</th></tr>\n";
    $query_time_total = 0.0;
      for($i=0;$i < $nb_queries;$i++) {
        list(, $cur_query) = each($saved_queries);
        $query_time_total += $cur_query[1];
        echo "<tr><td style='text-align:right;'>".($i+1)."</td>";
        echo "<td style='text-align:center;'>".(($cur_query[1] != 0) ? sprintf('%.6f',$cur_query[1]) : '&nbsp;')."</td>";
        echo "<td>".htmlspecialchars($cur_query[0])."</td></tr>\n";
      }
      echo "<tr><td colspan='3' style='text-align:center;'>Total duration of queries : ".sprintf('%.6f',$query_time_total)." s</td></tr>\n";
      echo "</table>\n";
   }
   else echo "<p>Aucun accès à la base de données</p>\n";
  echo "</div>\n";
}

// Affiche un message d'erreur
function sql_error($message) {
   global $f_db_connexion;
   $html = "<div style='border:4px solid red;background-color:white;margin:10px;'>\n<p style='font-weight:bold;color:red;'>Sorry, but an error occurred</p>\n";
   $html .= "<p>".nl2br($message)."</p>\n";
   $html .= "</div>\n";
   echo $html;
   if(defined('SEE_QUERIES')) {
      if(isset($f_db_connexion) && $f_db_connexion !== false) {
         echo "<div style='border:0;'background-color:white;margin:10px;'>\n";
         echo "<p style='text-align:center;font-weight:bold;'>Previous queries</p>\n";
         see_saved_queries();
         echo "</div>\n";
      }
   }
   exit;
}

//Fin des fonctions générales
?>

Pour que la class d'origine mysql reste compatible, on va légèrement la modifier.
Dans le fichier agb\db\MySQL.php, juste après
// originale class by phpbb group : http://www.phpbb.com
ajouter :

Code : Tout sélectionner

//On s'assure que MySQL est supporté
if (!function_exists('mysql_connect')) exit('Cet environnement ne supporte pas MySQL qui est requis pour utiliser cette classe');

À la fin du même fichier, juste avant ?> insérer :

Code : Tout sélectionner

define('TYPE_BASE_ALEX','MySQL');
include($chem_absolu."db/mysql_functions.".$alex_livre_ext);

Remplacer :

Code : Tout sélectionner

function alex_livre_sql($sqlserver, $sqluser, $sqlpassword, $database, $persistency = false)

par

Code : Tout sélectionner

function __construct($sqlserver, $sqluser, $sqlpassword, $database, $persistency = false)


Ensuite, pour ne rien changer à tous les appels mysql, nous allons créer une class mysqli mais de même nom que la class mysql d'origine.
Dans un fichier (utf-8) agb\db\MySQLi.php mettre :

Code : Tout sélectionner

<?php

//On s'assure que MySQLi est supporté
if (!function_exists('mysqli_connect')) exit('This environment does not support MySQLi that is required to use this class');

class alex_livre_sql {

  public $db_connect_id;
  public $query_result;
  public $saved_queries = array();
  public $row = array();
   public $rowset = array();
  public $num_queries = 0;

  //Connexion à Mysql puis à la base de données
  function __construct($db_host, $db_username, $db_password, $db_name, $persistency) {
    $this->db_connect_id = @mysqli_connect($db_host, $db_username, $db_password, $db_name);
    if ($this->db_connect_id) {
            if (defined('NAMES_UTF8'))
               $this->set_names('utf8');
         return $this->db_connect_id;
    }
    else sql_error("Could not connect to MySQL or to database.\nMySQL said : ".mysqli_connect_error());
  }

  function sql_close() {
    if ($this->db_connect_id) {
      if ($this->query_result) @mysqli_free_result($this->query_result);
      return @mysqli_close($this->db_connect_id);
    }
    else return false;
  }

  function sql_query($sql) {
    if (defined('SEE_QUERIES')) $q_start = microtime(true);
    $this->query_result = @mysqli_query($this->db_connect_id, $sql);
    if ($this->query_result !== false) {
      if (defined('SEE_QUERIES')) $this->saved_queries[] = array($sql, (microtime(true) - $q_start));
      ++$this->num_queries;
      return $this->query_result;
    }
    else {
      if (defined('SEE_QUERIES')) $this->saved_queries[] = array($sql, 0);
         sql_error("Query error.\nQuery is:".$sql."\nError ".@mysqli_errno($this->db_connect_id)."\nError message: ".@mysqli_error($this->db_connect_id)."\n");
      return false;
    }
  }

  function sql_numrows($query_id = 0) {
    return ($query_id) ? @mysqli_num_rows($query_id) : false;
  }

  function sql_affectedrows() {
    return ($this->db_connect_id) ? @mysqli_affected_rows($this->db_connect_id) : false;
  }

   function sql_numfields($query_id = 0)   {
      if(!$query_id)
         $query_id = $this->query_result;
      return ($query_id) ? @mysqli_num_fields($query_id) : false;
   }

   function sql_fieldname($offset, $query_id = 0) {
      if(!$query_id)
         $query_id = $this->query_result;
      return ($query_id) ? @mysqli_field_name($query_id, $offset) : false;
   }

   function sql_fieldtype($offset, $query_id = 0) {
      if(!$query_id)
         $query_id = $this->query_result;
      return ($query_id) ? @mysqli_field_type($query_id, $offset) : false;
   }

   function sql_fetchrow($query_id = 0)   {
      if(!$query_id)
         $query_id = $this->query_result;
      if($query_id) {
         $this->row[(int)$query_id] = @mysqli_fetch_array($query_id);
         return $this->row[(int)$query_id];
      }
      else
         return false;
   }

   function sql_fetchrowset($query_id = 0)   {
      if(!$query_id)
         $query_id = $this->query_result;
      if($query_id)   {
         unset($this->rowset[$query_id]);
         unset($this->row[$query_id]);
         while($this->rowset[$query_id] = @mysqli_fetch_array($query_id))
         {
            $result[] = $this->rowset[$query_id];
         }
         return $result;
      }
      else
         return false;
   }
   function sql_fetchfield($field, $rownum = -1, $query_id = 0) {
      if(!$query_id)
         $query_id = $this->query_result;
      if($query_id)   {
         if($rownum > -1)
            $result = @mysqli_result($query_id, $rownum, $field);
         else   {
            if(empty($this->row[$query_id]) && empty($this->rowset[$query_id]))   {
               if($this->sql_fetchrow())
                  $result = $this->row[$query_id][$field];
            }
            else {
               if($this->rowset[$query_id])
                  $result = $this->rowset[$query_id][$field];
               else if($this->row[$query_id])
                  $result = $this->row[$query_id][$field];
            }
         }
         return $result;
      }
      else
         return false;
   }

   function sql_rowseek($rownum, $query_id = 0) {
      if(!$query_id)
         $query_id = $this->query_result;
      return ($query_id) ? @mysqli_data_seek($query_id, $rownum) : false;
   }

   function sql_nextid(){
      return ($this->db_connect_id) ? @mysqli_insert_id($this->db_connect_id) : false;
   }

   function sql_freeresult($query_id = 0) {
      if(!$query_id)
         $query_id = $this->query_result;
      if ( $query_id )   {
         unset($this->row[$query_id]);
         unset($this->rowset[$query_id]);
         @mysqli_free_result($query_id);
         return true;
      }
      else
         return false;
   }

   //[modif oto] ajout pour SET NAMES utf8
   function set_names($names)   {
      return $this->sql_query('SET NAMES \''.$names.'\'');
   }

  function get_saved_queries() {
    return $this->saved_queries;
  }
}
define('TYPE_BASE_ALEX','MySQLi');

include($chem_absolu."db/mysql_functions.".$alex_livre_ext);

?>

Au début du fichier agb\config\config_base.php, juste après <?php, on ajoute les lignes qui n'existeraient pas :

Code : Tout sélectionner

<?php
define('NAMES_UTF8', 1);
//define('SEE_QUERIES', 1);
//$database_type = "MySQL";
$database_type = "MySQLi";

Nota : Il « suffit » de commenter la ligne $database_type = "MySQLi"; et de décommenter //$database_type = "MySQL"; pour revenir au fonctionnement normal avec mysql.
Et, pour voir les requêtes effectuées sur une page, il faut décommenter //define('SEE_QUERIES', 1); et ne pas oublier de le re-commenter après les essais.

D'origine, les appels à une class de gestion de basse de données se font par variable, par exemple dans agb\include\livre_include.php par
include($chem_absolu."db/".$database_type.".".$alex_livre_ext);
donc, pas besoin de modifier.

Théoriquement, nous en avons terminé avec le remplacement de mysql par mysqli.
J'écris "théoriquement" car, comme noté en préambule, cette procédure est écrite a posteriori et je peux ne pas me rappeler d'autres modifications.

on en arrive maintenant à la gestion des erreurs du style :
Deprecated: Methods with the same name as their class will not be constructors in a future version of PHP; ErrorManager has a deprecated constructor in xxx\templates\modelixe\ErrorManager.php on line 52
On pourrait en rester là et masquer les avertissements, mais, rien ne dit qu'avec PHP 7.0.5 ou autre, ça ne se transformera pas en erreur fatale, donc, il est préférable de traiter ce problème dès maintenant.

On traite d'abord la class « Parent » ErrorManager :
Dans le fichier agb\templates\modelixe\ErrorManager.php remplacer :

Code : Tout sélectionner

function ErrorManager($errorManagerSystem = '', $level = '', $escape = '', $file = '', $alarme = ''){

par :

Code : Tout sélectionner

function __construct($errorManagerSystem = '', $level = '', $escape = '', $file = '', $alarme = ''){

Puis on va traiter la class « Enfant » Modelixe :
Dans le fichier agb\templates\modelixe\ModeliXe.php remplacer

Code : Tout sélectionner

    function ModeliXe ($template, $sessionParameter = '', $templateFileParameter = '', $cacheDelay = -1, $ok_cache = false, $chem_template = ''){

      $this -> ok_cache = $ok_cache;
      if ($chem_template){
         $this -> mXTemplatePath = $chem_template;
      }

        $this -> ErrorManager();

par

Code : Tout sélectionner

    function __construct($template, $sessionParameter = '', $templateFileParameter = '', $cacheDelay = -1, $ok_cache = false, $chem_template = ''){
       parent::__construct();
      $this -> ok_cache = $ok_cache;
      if ($chem_template){
         $this -> mXTemplatePath = $chem_template;
      }

        //$this -> ErrorManager();


Il y a peut-être mieux à faire ou à faire autrement, toujours est-il que @lex Guestbook semble fonctionner correctement sous PHP 7.0.3 et MySQL 5.7.11 sans générer d'erreur ou d'avertissement.

Et voilou :pausecaffé:

Je répète : À n'effectuer qu'après sauvegarde des fichiers à modifier. J'ai pu oublier une modification.
Ce n'est pas par ce que l'erreur se propage qu'elle devient vérité. Gandhi

Jean-Pierre
Messages : 207
Inscription : Mer 09 Août 2006, 10:19
Contact :

Re: PHP 7 et @lex Guestbook

Messagepar Jean-Pierre » Dim 28 Fév 2016, 18:19

Bonjour :hello:

Merci Oto de débroussailler autant devant nous.

En effet et à mon avis, lorsque la version 7 de PHP sera devenue "obligatoire", si jamais aucune nouvelle version d'@lex Guestbook n'est sortie entre ; ce sera le déclin signé, voire la disparition de ce merveilleux Livre d'Or.

Hé oui tout le monde ne peut se prendre la tête à reprendre certaines parties de code, ni n'en a les compétences.

Je suppose que dans l'ombre nos bien aimés admins :langue1: œuvrent en ce sens ;-)

Bon courage à eux et encore merci Oto de toutes tes indications si précieuses :super:

fandemixmaster
Messages : 21
Inscription : Mar 28 Jan 2014, 16:27

Re: PHP 7 et @lex Guestbook

Messagepar fandemixmaster » Mar 21 Fév 2017, 01:05

Merci beaucoup :)


Revenir vers « Suggestions d'amélioration du script »

Qui est en ligne ?

Utilisateurs parcourant ce forum : Aucun utilisateur inscrit et 3 invités