Blog ENI : Toute la veille numérique !
🐠 -25€ dès 75€ 
+ 7 jours d'accès à la Bibliothèque Numérique ENI. Cliquez ici
Accès illimité 24h/24 à tous nos livres & vidéos ! 
Découvrez la Bibliothèque Numérique ENI. Cliquez ici
  1. Livres et vidéos
  2. PHP 8
  3. Accéder aux bases de données
Extrait - PHP 8 Développez un site web dynamique et interactif (2e édition)
Extraits du livre
PHP 8 Développez un site web dynamique et interactif (2e édition) Revenir à la page d'achat du livre

Accéder aux bases de données

Introduction

1. Vue d’ensemble

L’utilisation d’une base de données SQL est souvent indispensable pour mettre en place un site web dynamique. C’est en effet un moyen standardisé de stocker des données utiles pour le site :

  • Liste des utilisateurs avec leurs préférences.

  • Catalogue de produits.

  • Trace des transactions effectuées.

PHP propose un support natif pour un grand nombre de bases de données, parmi lesquelles MySQL, Oracle, Microsoft SQL Server, Informix, Sybase. Par ailleurs, PHP supporte ODBC (Open DataBase Connectivity) et peut donc accéder à toute base de données supportant ODBC.

En complément, PHP est livré avec SQLite, librairie qui implémente un moteur de base de données SQL. SQLite peut être utilisé pour stocker des données dans une base SQL, sans avoir à mettre en place la partie serveur de la base de données (comme c’est le cas avec MySQL, Oracle, etc.).

Dans ce chapitre, nous étudierons MySQL et Oracle.

Typiquement, lors de l’utilisation d’une base de données, le script PHP a besoin d’effectuer une ou plusieurs des tâches suivantes :

  • Se connecter et se déconnecter.

  • Lire des données (une ou plusieurs lignes).

  • Mettre à jour des données (ajout, modification ou suppression).

Ces différentes tâches types sont étudiées...

Utilisation de MySQL

1. Préambule

L’extension MySQLi (préfixe mysqli_) permet d’accéder à une base de données.

Cette extension peut être utilisée soit sous une forme procédurale, soit sous une forme objet.

Dans sa forme orientée objet, l’extension MySQLi propose trois classes principales :

mysqli

Connexion entre PHP et MySQL.

mysqli_stmt

Requête préparée.

mysqli_result

Résultat de l’exécution d’une requête.

Ces différentes classes proposent des méthodes qui permettent d’effectuer les différentes actions (exécution d’une requête, récupération du résultat, etc.).

Dans sa forme procédurale, l’extension MySQLi propose des fonctions qui permettent d’effectuer les mêmes actions. De façon transparente, plusieurs de ces fonctions retournent ou acceptent en paramètres des objets de type mysqli ou mysqli_result.

Dans cet ouvrage, nous présentons uniquement la forme procédurale de l’extension MySQLi.

L’extension MySQLi permet d’utiliser les requêtes préparées de MySQL.

Une requête préparée est une requête qui contient des paramètres matérialisés par un point d’interrogation (?).

Exemples

SELECT * FROM article WHERE id = ? 
INSERT INTO article(libelle,prix) VALUES(?,?) 

À l’inverse, une requête non préparée est une requête dans laquelle toutes les valeurs sont spécifiées.

Exemples

SELECT * FROM article WHERE id = 1 
INSERT INTO article(libelle,prix) VALUES('Bananes',10.5) 

Dans la suite de ce chapitre, nous présenterons comment exécuter des requêtes de lecture et de mise à jour, d’abord avec des requêtes non préparées (cf. section Utiliser des requêtes non préparées), puis avec des requêtes préparées (cf. section Utiliser des requêtes préparées).

2. Connexion et déconnexion

a. Connexion

La fonction mysqli_connect permet d’établir une connexion avec une base MySQL.

Syntaxe

objet mysqli_connect([chaîne hôte [, chaîne utilisateur [,  
chaîne mot_de_passe [, chaîne nom_base [, entier port...

Utilisation d’Oracle

1. Préambule

L’extension « Oracle OCI8 », contrairement à ce que son nom laisse penser, peut être utilisée pour accéder à n’importe quelle version d’Oracle. Cette extension est très complète et très puissante ; elle permet notamment d’utiliser les types LOB et ROWID et d’établir des liaisons entre les variables PHP et des variables dans la requête SQL (notion de « bind variable »).

2. Environnement NLS

L’environnement NLS (National Language Support), utilisé lors de l’exécution des requêtes, est défini par les variables d’environnement habituelles positionnées sur le serveur qui exécute PHP :

  • NLS_LANG

  • NLS_DATE_FORMAT...

Si ces variables d’environnement ne sont pas positionnées, les paramètres par défaut du serveur Oracle sont pris en compte.

Cette situation peut conduire à des différences de fonctionnement d’un même programme entre deux environnements. Par exemple, si vous récupérez dans une requête une colonne de type DATE, une conversion en chaîne est automatiquement effectuée (car PHP ne supporte pas le type DATE en tant que tel) selon le paramètre NLS_DATE_FORMAT actif ; selon la configuration et l’environnement, la chaîne récupérée peut avoir des formats différents (DD/MM/YYYY, DD-MON-YY...).

Des problèmes analogues se produisent avec les données numériques qui sont, elles aussi, converties en chaîne avec un séparateur décimal et un séparateur de groupe qui peut varier selon l’environnement.

Si l’environnement n’est pas maîtrisé, il est possible d’agir au niveau du code PHP pour obtenir un code portable d’un environnement à l’autre :

  • soit en effectuant systématiquement des conversions explicites dans les ordres SQL (TO_CHAR(SYSDATE,’DD/MM/YYYY’), TO_DATE(’31/08/2001’,’DD/MM/YYYY’), TO_CHAR(prix,’9999.99’), TO_NUMBER(’123.45’,’999.99’) par exemple).

  • soit en exécutant, après chaque ouverture de session, des requêtes ALTER SESSION (ALTER SESSION SET NLS_DATE_FORMAT...

PHP Data Objects (PDO)

PHP Data Objects (PDO) est une extension qui définit une interface uniforme pour accéder aux bases de données en PHP. L’accès à une base de données à travers PDO s’effectue par l’intermédiaire d’un driver qui expose les fonctionnalités de la base de données.

Il faut bien noter que PDO ne fournit pas une couche d’abstraction de la base de données mais une couche d’abstraction de l’accès aux bases de données. Les requêtes que vous écrivez doivent respecter la syntaxe de la base de données que vous utilisez ; PDO ne récrit pas les requêtes SQL et n’émule pas les fonctionnalités manquantes (à l’exception des requêtes paramétrées si besoin).

De nombreuses bases de données disposent d’un driver PDO parmi lesquelles MySQL, et Oracle.

PDO est une extension orientée objet qui est constituée de trois classes :

  • PDO : connexion entre PHP et la base de données.

  • PDOStatement : requête préparée, et, après exécution, résultat associé.

  • PDOException : exception levée par PDO.

Dans ce chapitre, nous présenterons cette extension par l’intermédiaire d’un simple exemple commenté :

<?php 
// Définition des paramètres...

Gestion des apostrophes dans le texte des requêtes

Dans le cas de l’utilisation de requêtes non préparées, un problème peut se poser si une chaîne de caractères littérale présente dans une requête contient une apostrophe.

Exemple (insertion en base d’une donnée qui contient une apostrophe)

<?php 
// Donnée qui pose problème (peut être saisie innocemment  
// dans un formulaire). 
$libellé = "Pomme d'api"; 
$prix = 10; 
// Requête. 
$requête = "INSERT INTO articles(libelle,prix) " . 
           "VALUES('$libellé',$prix)"; 
echo "$requête<br />"; 
// Exécution avec MySQL. 
echo "<p><b>MySQL</b><br />"; 
mysqli_report(MYSQLI_REPORT_OFF); // Désactiver le rapport d'erreur  
$connexion = mysqli_connect(); 
$ok = mysqli_select_db($connexion,'diane'); 
$résultat = mysqli_query($connexion,$requête); 
echo mysqli_error($connexion),'<br />'; // MySQL ne génère pas d'alerte 
// Exécution avec Oracle. 
echo "<p><b>Oracle</b><br />"; 
$connexion = oci_connect('demeter','demeter','diane'); 
if ($curseur = oci_parse($connexion,$requête)) {
  $résultat = oci_execute($curseur); 
}
?> 

Résultat

INSERT INTO articles(libelle,prix) VALUES('Pomme d'api',10) 
 
MySQL 
You have an error in your SQL syntax; check the manual that corresponds  
to your MySQL server version for the right syntax to use near 'api',10)' 
at line 1 
 
Oracle 
Warning: oci_parse(): ORA-01756: quoted string not properly terminated  
in /app/scripts/index.php on line 19  

En SQL, le délimiteur de chaîne de caractères est l’apostrophe : si une requête envoie la chaîne ’Pomme d’api’ à la base, cette dernière va interpréter ’Pomme d’ comme une chaîne et ne saura pas quoi faire du reste (api’).

Pour régler ce problème, il faut indiquer à...

Exemples d’intégration dans des formulaires

1. Vue d’ensemble

Pour terminer ce chapitre, nous allons présenter quelques exemples d’accès aux bases de données à partir de formulaires.

Quatre exemples sont proposés :

  • la construction d’une liste de sélection dans un formulaire ;

  • un formulaire qui affiche une liste ;

  • un formulaire qui permet de saisir des données dans une liste ;

  • un formulaire de recherche et de saisie de type "page".

Pour des raisons de concision, dans ces exemples, le contrôle de la saisie est pratiquement absent, et la mise en forme est très simple.

Les exemples ont été conçus pour fonctionner de la même manière avec MySQL et Oracle. Pour cela, l’accès aux bases de données s’effectue à l’aide de plusieurs fonctions qui sont implémentées dans une librairie spécifique à chaque produit. Pour faire fonctionner un exemple sur une base de données particulière, il suffit d’inclure la librairie correspondante.

Les fonctions utilisées pour l’accès aux bases de données sont les suivantes :

connexion

Connexion à la base de données.

sélectionner_articles

Sélection de tous les articles.

lire_article_suivant

Lecture de l’article suivant dans le résultat de la requête de sélection de tous les articles.

sélectionner_un_article

Sélection d’un article dont l’identifiant est passé en paramètre.

enregistrer_article

Enregistrement des modifications d’un article.

enregistrer_articles

Enregistrement des mises à jour (création, modification, suppression) d’une liste d’articles (en liaison avec le formulaire de saisie en liste).

Syntaxes

booléen connexion(&$connexion,&$erreur) 
booléen sélectionner_articles($connexion,&$requête,&$erreur) 
mixte lire_article_suivant($connexion,$requête,&$article,&$erreur) 
booléen sélectionner_un_article($connexion,$identifiant,&$article,&$erreur) 
booléen enregistrer_article($connexion,$article,&$erreur) 
mixte enregistrer_articles($connexion,$lignes,&$erreur) 

Avec :

$connexion

Identifiant de la connexion retourné...