Construire un Code PHP Portable

Le grand souci des développeurs est de construire un code qui soit à la fois efficace, propre et portable. L'efficacité en soit est une nécessité, la propreté du code permet d'être assuré que l'on peut collaborer avec d'autres développeurs et faire en sorte qu'ils comprennent rapidement les routines que l'on a programmé, et la portabilité permet de s'assurer que ce que l'on a écrit pourra non seulement être exécuté sur un maximum de sytèmes, mais également être facilement modifié pour pouvoir fonctionner sur d'autres systèmes.

Si certains développeurs connaissent exactement le système et l'environnement sur lequel leur script PHP va tourner, la vaste majorité, dont évidemment l'ensemble des programmeurs qui offrent leurs scripts en opensource, ne peuvent absolument pas prévoir sur quel système leur création va être utilisée, ce qui risque donc de générer des erreurs dans des routines qui marchaient parfaitement sur la machine de développement.

Nous avons donc réunis un ensemble de suggestions pour faire en sorte que cette transition de la machine de développement à la machine d'utilisation se fasse avec le moins de problèmes possible.

1) Passer en mode E_ALL
PHP dispose d'un large éventail d'options pour le rapport d'erreur. Par défaut, le fichier php.ini est réglé ainsi:

error_reporting = E_ALL & ~E_NOTICE ; Show all errors except for notices

Le commentaire parle de lui-même: en cas d'erreur, PHP affichera toutes les erreurs, sauf les erreurs non-fatales (variables non-initialisées, ...). Il est préférable quand on développe un script d'avoir réglé son fichier php.ini avec E_ALL seul (rapport pour toutes les erreurs). En effet, on ne peut jamais prévoir si l'utilisateur n'a pas lui-même mis son fichier php.ini en mode E_ALL.
Une alternative à la modification du fichier php.ini est de mettre en première ligne du script l'appel de fonction suivant: error_reporting(E_ALL); .
Ajoutons à cela que la recherche de bugs intempestifs et introuvables est d'autant plus facilitée...

2) La bonne balise
Exemple de la permissivité outrancière offerte par PHP ici et là, le fait de pouvoir choisir ses propres balises d'ouverture ravit plus d'un développeur qui pense pouvoir travailler plus vite en ayant trois lettres en moins à taper. En effet, si les balises d'ouverture et de fermeture officielles sont <?php et ?>, d'autres sont également acceptées:
- <? ... ?> : le format datant de PHP/FI 2.0
- <% ... %> : pour les nostalgique d'ASP, s'il en est
- <script language="php"> ... </script> : pour les éditeurs WYSIWYG récalcitrants.

Malgré ses solutions de facilité (pour les deux premières options, en tout cas), il faut s'en tenir au <?php officiel. Non seulement les balises <? et <% peuvent porter à confusion tant pour le serveur que le développeur (ce sont respectivement les mêmes balises que XML et ASP), mais il est également possible de bloquer ces deux balises par le biais du fichier php.ini.

3) Les variables
Autre aspect de PHP sur lequel il ne faut pas toujours compter: que les variables GET, POST, d'environnement, de session/serveur ou de cookies (EGPCS ou GPC) soient des variables globales normales. Parce que l'option register_globals du fichier php.ini peut être inactivée sur certains systèmes, il vaut toujours mieux faire appel aux variables GPC via les tableaux du type $HTTP_*_VARS (ou $_* , * pouvant prendre la forme GET, POST, ENV, SERVER, SESSION, COOKIE, REQUEST selon l'usage). Ainsi, pour récuperer les données du champ "login" d'un formulaire utilisant la méthode POST, il sera préférable d'utiliser $HTTP_POST_VARS['login'] ou $_POST['login'] plutôt que directement $login.
Ajoutons qu'utiliser des variables globales peut facilement amener à des failles de sécurité, les internautes pouvant entrer leurs propres variables globales dans les scripts PHP, ce qui n'est jamais à prendre à la légère.

4) La base de données
Lorsqu'un script est sensé utiliser une base de donnée, il ne faut jamais prendre pour évidente l'existence de celle-ci, ni des tables que l'on cherche à accéder. De fait, afin d'offrir le plus de chance aux développeurs d'adapter rapidement votre script à leur environnement, il ne faut jamais mettre les noms des bases et des tables "en dur" dans vos requêtes SQL., mais plutôt mettre ses noms dans des variables clairement accessibles et modifiables, par exemple depuis un fichier externe où se trouverait la configuration générale.
Plus largement, il peut se révéler utile de prévoir les évolutions futures, en faisant appel à une couche d'abstraction de base de données, telle que MetaBase ou ADOdb, qui permettent de simplifier l'intégration à une base de données autre que celle initialement prévue.

5) Les chemins d'accés
Si un script doit accéder à un fichier (en lecture comme en écriture), ou lors de l'inclusion d'un fichier via require(), include(), readfile() ou autre, il faut prendre en compte le fait que le script ne sera pas forcément lancé sur une machine Windows (\dossier\fichier.inc) ou UNIX (/dossier/fichier.inc). Les chemins d'accès aux fichiers se doivent donc de refléter cela: il ne faut jamais les coder en dur, mais plutôt faire appel aux fonctionnalités offertes par PHP: $DOCUMENT_ROOT ou $_SERVER['DOCUMENT_ROOT'] (la racine du système de fichier: var/www/);
$PHP_SELF (le nom du fichier en cours);
$_SERVER["PATH_TRANSLATED"](le chemin absolu du script sur le système: /users/phptest/public/www/test.php);
__FILE__ (le nom du fichier en cours);
$PATH_INFO (l'URI d'accés au script: /dossier/sous-dossier/);
$PATH_TRANSLATED (équivalent de $PATH_INFO en absolu sur le système: /public/var/web/php/dossier/sous-dossier/);
$HTTP_SERVER_VARS['SERVER_NAME'] (le nom du serveur: www.mon-site.com);
... et les autres, selon vos besoins... Les noms de toutes les variables acceptées par PHP sont accessibles via phpinfo(INFO_VARIABLES); .

6) Les Magic Quotes
Toujours sur le thème des bases de données, l'utilisation des Magic Quotes peut se révéler dangereuse... Parce que, utilisés en combinaison avec addslashes(), ils ajoutent des anti-slashes (\) en trop dans les requêtes SQL, les Magic Quotes peuvent facilement briser le bon fonctionnement d'un script.
Les Magic Quotes sont à l'origine un moyen de se faciliter la vie automatiquement, en ajoutant des caractères de sortie là où en faudrait. Mais cette fonction est désormais mal perçue, du fait du nombre d'erreurs possibles. De fait, il est conseillé de ne jamais partir à l'aveuglette quand on entre une chaîne dans une base de données, et de toujours tester si l'option Magic Quotes est activée. Si elle l'est, on ne fait pas appel à addslashes(), sinon, on y fait appel:

// a appeller quand une variable est insérée directement
// dans une base de données, en provenance de $_REQUEST ($_GET...)
function safe_addslashes($string)
  {
  // Using a static variable, speeds up multiple calls.
  static $setting=-1;
  if($setting === -1)
    {
    $setting = get_magic_quotes_gpc();
    }
  return ($setting) ? $string : addslashes($string);
  }

// a appeller quand une variable en provencance de $_REQUEST
// est affichée à l'écran, ou une source de données qui n'est
// pas affectée par les guillemets ('')
function safe_stripslashes($string)
  {
  static $setting = -1;
  if($setting === -1)
    {
    $setting = get_magic_quotes_gpc();
    }
  return ($setting) ? stripslashes($string) : $string;
  }

 

[Xavier Borderie, 17 décembre 2002 , JDNet]