PHP: l'extension MySQL est obsolète

Décembre 2016


PHP est un superbe langage de programmation pour les serveurs web, mais il n'est pas très bon pour stocker des données de manière structurées tout seul, ainsi il lui faut des extensions lui permettant de se connecter et d'utiliser des SGBD, dont le populaire MySQL. C'est un moteur de BDD qui se respecte, et dont le développement est actif et l'utilisation populaire, particulièrement dans les installations [W/L/M]AMP.
Toutefois, son utilisation via PHP se fait (historiquement) via l'extension MySQL (fonctions
mysql_*
) de PHP, qui est obsolète! La BDD elle-même n'est pas obsolète en revanche.

Accrochez-vous, c'est un peu long... Si vous ne voulez pas lire, retenez juste ceci: bannissez les fonctions
mysql_*
et dirigez vous vers mysqli ou PDO.

Obsolète depuis PHP 5.5... disparue dans PHP 7.0

PHP 5.5.0 est sorti officiellement le 20 Juin 2013 (cf l'archive 2013 de PHP avec les notes de sorties). Dans cette version, il a été décidé que l'extension MySQL serait obsolète.
Plusieurs raisons à cela ont été exposées sur la page de RFC dédiée à cette décision. Cette fiche de FAQ les récapitule.

Par ailleurs, à partir de PHP version 7.0, l'extension n'existe plus ! Elle a officiellement été retirée car non maintenue et devenue incompatible avec la nouvelle version du célèbre langage.

Donc, qui dit obsolète, dit qu'il y a de bonnes raisons de ne plus s'en servir. Pour que vous n'oubliiez pas cela, utiliser les fonctions
mysql_*
déclenche un avertissement (pas une erreur)
E_DEPRECATED
dans votre code par défaut sur PHP 5.5 et plus.

Un mauvais design

Plus de 15 ans d'histoire

L'extension MySQL a été introduite lors de PHP 2.0, donc avant 1998, année de sortie de PHP 3. Les techniques d'il y a plus de 15 ans ne sont pas forcément efficaces aujourd'hui, surtout dans l'informatique, qui évolue très vite. Ce qui explique d'ailleurs pourquoi cette extension est relativement lente par rapport aux autres disponibles... et explique aussi l'absence de plusieurs fonctionnalités importantes aujourd'hui, citées plus bas.

Les connexions aux BDD: la dernière est celle par défaut

Les fonctions
mysql_*
, si on ne leur précise pas, considèrent que la BDD sur laquelle agir est celle dont la connexion est la plus récente. Ceci est problématique dans 2 cas:
  • quand on gère plusieurs bases de données à la fois: un oubli, et votre requête SQL part dans la mauvaise base.
  • pour traquer les bugs: aucune variable ne décrit explicitement la connexion, donc impossible de savoir précisément d'où viens le problème: l'extension se plaindra, c'est tout. Impossible de remonter jusqu'à la création de la connexion via un IDE/débogueur PHP, il faut trouver le
    mysql_connect
    à la main et ajouter du code de débogage soi-même pour savoir ce qui s'est passé.

La gestion d'erreur? Quelle gestion d'erreur?

PHP 5 a apporté un modèle tout droit venu de la programmation orienté objet: les exceptions. L'extension MySQL est trop vieille et n'a jamais été mise à jour pour qu'elle les utilise, aussi la gestion des erreurs s'effectue-t-elle via un appel à mysql_error(). Le gros désavantage de cette technique est que si on veut intercepter une erreur dans la totalité des cas, il faut mettre son bout de code de gestion d'erreur après chaque fonction
mysql_*
!

Les exceptions permettent d'interrompre l'exécution d'un bloc de code et d'aller directement à la gestion d'erreur, ce qui simplifie le code non seulement pour le programmeur mais aussi pour PHP: les exceptions constituent un système passif, déclenché uniquement quand les fonctions utilisées signalent elle-mêmes une erreur. Avec l'autre méthode, on vérifie à chaque fois si tout c'est bien passé, et la plupart du temps tout ce passe bien... travail pour rien.

Conçu pour MySQL 3.23

Les utilisateurs un peu plus experts en (My)SQL se verront déçus de ne pas pouvoir profiter de certaines fonctions apparues après la 3.23, l'extension n'ayant pas été mise à jour avec de nouvelles fonctionnalités.
On remarquera donc l'absence de procédures SQL, qui peuvent pourtant s'avérer très pratiques.
Selon certains, l'extension aurait aussi du mal a gérer certains codages texte.

Cryptage des connexions

Les connexions aux BDD distantes peuvent être sécurisées par SSL (Secure Socket Layer), mais pas par TLS (Transport Layer Security). Comme l'ont montré de récents événements (à la date d'écriture, HeartBleed d'OpenSSL), SSL est un protocole qui ne devrait plus être utilisé et remplacé par TLS 1.1 ou plus pour de multiples raisons, qui ne seront pas décrites ici. L'extension MySQL ne supporte pas les connexions sécurisées par TLS, et donc force tout le monde à se réduire à un protocole de sécurité qui devrait lui aussi être considéré comme obsolète.

Pas de requêtes préparées

Avez-vous remarqué le titre en gras et souligné? C'est peut-être le point le plus important de toute cette fiche de FAQ:
L'extension MySQL n'a pas de requêtes préparées.
Kézaquo, et pourquoi est-ce si important? Les requêtes SQL sont très souvent variables en fonction de choix de l'utilisateur; la solution la plus simple (et malheureusement la plus populaire) ressemble à ceci:
mysql_query('UPDATE membres SET nom="'.$_GET['nom'].'" WHERE nom="'.$nom.'"');

Tout va bien, vous avez mis des guillemets autour des données utilisateurs. Dommage, c'est loin d'être suffisant: un utilisateur peut devenir administrateur en accédant à
changer-nom.php?nom=%22%20admin%3D1%20nom%3D%22USERNAME
. Un tutoriel X ou Y vous dira d'utiliser
mysql_real_escape_string
, qui est certes efficace mais (honnêtement) longue et moche, et à force de s'en servir on l'utilise 2 fois d'affilée ou pas du tout sur un paramètre...
Les requêtes préparées proposent une solution élégante à tout ça: vous préparez la structure de votre requête, puis l'exécutez avec les paramètres voulus (exemple PDO):
$req = $pdo->prepare('UPDATE membres SET nom=:nouveaunom WHERE nom=:nom');
$req->execute(array(
    "nouveaunom" => $_GET['nom'],
    "nom" => $nom
));
Voilà, sans jamais vous soucier d'une possibilité d'injection SQL. Le sale travail est fait pour vous.

Un danger pour le futur

L'extension touchant à la fin de sa vie, sa suppression de PHP est imminente, et votre site aussi s'il s'en sert... Actuellement il y a toute une "culture" autour de l'extension, qui est menée à disparaître, mais sans le savoir: énormément de tutoriels et de personnes vous recommanderont encore d'utiliser les fonctions
mysql_*
, ignorant tout de leur future suppression, de leurs désavantages et de cet article que vous êtes en train de lire. Vous l'avez compris, il faut estomper la culture autour de l'extension MySQL. Plus facile à dire qu'à faire...

C'est pour cela qu'il faut absolument convertir vos scripts, sites voire CMS si possible vers une autre API d'accès aux BDD. Plus la transition est faite tôt, moins il y aura de problèmes: votre projet n'est peut-être pas (encore) gros, et la documentation de l'extension reste encore très accessible, comme les tutos de conversion. Profitez-en, faites le "avant qu'il ne soit trop tard".

Les problèmes de design évoqués plus haut font de l'extension MySQL quelque chose de pas très facile à convertir. Mais une fois le pas franchi, si le besoin s'en ressent la migration d'un connecteur de BDD à un autre sera bien plus simple: les APIs modernes ont toutes (plus ou moins) la même structure.

Peu et bientôt plus maintenu

L'absence de maintenance du code entraîne un risque majeur: les failles de sécurité trouvés dedans ne seront peut-être jamais corrigées. C'est donc des milliers de sites qui seraient en danger si le cas se présentait. Tachez de ne pas faire partie de ceux-là.

Alors on se sert de quoi?

La réponse est simple, mais faites votre choix:
  • PDO
    • Interface orientée objet uniquement
    • Marche sur plusieurs SGDB: MySQL, MSSQL, sqlite, ...
  • mysqli
    • Interface orientée objet et modèle fonctionnel, compatible entre eux
    • Forte ressemblance à l'extension MySQL

Faites-le savoir aux autres

Si vous croisez quelqu'un conseiller l'extension MySQL ou en train d'appendre à s'en servir, faites votre possible pour lui faire comprendre son erreur: dites-lui et mettez cet article en lien, qui exposera les arguments contre son utilisation au lieu que vous le fassiez en écrivant une réponse longue et fastidieuse.

Cet article de FAQ est sous licence CC BY-SA et a été initialement rédigé par gravgun.

A voir également :

Ce document intitulé «  PHP: l'extension MySQL est obsolète  » issu de CommentCaMarche (www.commentcamarche.net) est mis à disposition sous les termes de la licence Creative Commons. Vous pouvez copier, modifier des copies de cette page, dans les conditions fixées par la licence, tant que cette note apparaît clairement.