Serveur - PHP Base de données
MySQL et POSTGRESQL sont des bases de données implémentant le langage de requête SQL. Cette partie suppose connue les principes des bases de données relationnelles.
Il existe des outils libres et gratuits développés par la communauté des programmeurs libres : phpMyAdmin et phpPGAdmin qui permettent l’administration des bases de données MySQL et POSTGRESQL avec PHP.
Attention
Les exemples de cette page utilisent une base de données MySQL, en mode procédural. Dans le cas d’une base Postgres, voir tout en bas de cette page.
Connexion#
Pour se connecter à une base depuis PHP, il faut spécifier un nom de serveur, un nom d’utilisateur, un mot de passe et un nom de base.
Les fonctions de connexion Mysqli :
mysqli_connect($server, $user, $password, $base)
: se connecte au serveur$server
en tant qu’utilisateur$user
avec le mot de passe$password
sur la base$base
. Retourne l’identifiant de connexion si succès,FALSE
sinon.mysqli_close([$id])
: permet de fermer la connexion
Connexion simple
<?php
$link = mysqli_connect('localhost', 'my_user', 'my_password', 'my_db');
if (!$link) {
die('Erreur de connexion');
} else {
echo 'Succès... ';
}
?>
Afin de se prémunir des éventuels problèmes d’encodage entre PHP et la base de données, il est également préférable d’ajouter
<?php
mysqli_set_charset($link, "utf8");
?>
On pourra avantageusement intégrer ce code dans un fichier que l’on pourra joindre par include()
. C’est aussi un moyen de sécuriser le mot de passe de connexion.
Requêtes#
Pour envoyer une requête à une base de donnée :
mysqli_query($link, $sql)
: prends en paramètre le lien de la connexion et une chaîne de caractères qui contient la requête écrite en SQL. RetourneTRUE
en cas de résultat,FALSE
si échec.
Les requêtes les plus couramment utilisées sont :
CREATE
(création d’une table)SELECT
(sélection)INSERT
(insertion)UPDATE
(mise à jour des données)DELETE
(suppression)ALTER
(modification d’une table)
Envoi d'une requête
<?php
$results = mysqli_query($link, "SELECT name, mail FROM users WHERE id=$id");
?>
Cet exemple sélectionne le nom et l’adresse mail de l’utilisateur qui a pour id
la valeur de la variable $id
.
Récupération des résultats#
Le résultat $results
est de type mysql_result
. Pour afficher son contenu, il suffit alors d’itérer sur ce résultat, tel un tableau associatif. Les clés du tableau étant les valeurs des champs extraits dans la requête SQL.
Dans notre cas, $result
contient deux clés, $result["name"]
et $result["mail"]
:
Récupération des résultats
<?php
foreach ($results as $result) {
// $result est un tableau associatif
echo $result["name"], $result["mail"];
}
?>
Autres méthodes de récupération des résultats
Autres méthodes de récupération des résultats#
Il existe d’autres méthodes pour récupérer les résultats d’une requête :
mysqli_fetch_row($result)
: retourne un tableau simple. Les clés du tableau étant des indices sans lien avec les champs de la requête SQLmysqli_fetch_assoc($result)
: retourne un tableau associatif. Les clés du tableau étant les valeurs des champs de la requête SQLmysqli_fetch_object($result)
: retourne un objet. Les attributs de l’objet correspondent aux champs de la requête SQL
Dans les 3 cas, les fonctions retournent false
s’il n’y a plus aucune ligne, leur utilisation est donc basée sur une boucle while
:
<?php
// solution préconisee: extraire des tableaux associatifs.
$requete = "SELECT * FROM users";
if ($result = mysqli_query($link, $requete)) {
while ($ligne = mysqli_fetch_assoc($result)) {
// $ligne est un tableau associatif
// contient par exemple $ligne["id"], $ligne["nom"], etc.
}
} else {
echo "Erreur de requête de base de données.";
}
?>
<?php
// tableau simple
$requete = "SELECT * FROM users";
if ($result = mysqli_query($link, $requete)) {
while ($ligne = mysqli_fetch_row($result)) {
// $ligne est un tableau simple
// contient par exemple $ligne[0], $ligne[1], etc.
}
} else {
echo "Erreur de requête de base de données.";
}
?>
<?php
// objet
$requet = "SELECT * FROM users";
if ($result = mysqli_query($link, $requete)) {
while ($ligne = mysqli_fetch_object($result)) {
// $ligne est un objet
// contient par exemple $ligne->id, $ligne->nom, etc.
}
} else {
echo "Erreur de requête de base de données.";
}
?>
Dans le cas de requêtes préparées, la fonction est mysqli_stmt_fetch($requete)
, mais il faut d'abord lier des variables aux résultats avec mysqli_stmt_bind_result($requete, $var1, $var2)
Alternative à mysqli_stmt_get_result
<?php
// on lie des variables aux resultats
mysqli_stmt_bind_result($requete, $id, $nom_departement);
// on parcours et on affiche les variables
while (mysqli_stmt_fetch($requete)) {
echo $id, $nom_departement;
}
?>
Exercice - BDD#
- créez la connection à la base avec
mysqli_connect
Données de connexion à la BDD geobase
Voici les infos pour la base de données MySQL
- serveur :
u2.ensg.eu
- base :
geobase
- utilisateur :
geo
- mot de passe :
''
(chaine de caractères vide) - tables (d’autres champs ne sont pas précisés ici):
regions
(champsinsee
,nom
)departements
(champsinsee
,region_insee
,nom
)communes
(champsinsee
,departement_insee
,nom
,surface
,geometry
)
- base :
- ou export disponible
Attention, les clés étrangères sont basées sur le champ insee
, qui est une chaine de caractères.
- stockez cette connexion de manière globale dans Flight
<?php
// stocker une variable globale
Flight::set('db', $var);
// récupérer la variable
Flight::get('db');
?>
- créez une nouvelle route
/departements
- ajoutez une requête qui sélectionne les nom et numéro insee de tous les départements français ( champs :
insee
,nom
, de la tabledepartements
) - créez un tableau associatif des départements, et envoyez à la vue
departements.php
- affichez le contenu total dans un tableau HTML. Nombre de lignes égal le nombre de départements, nombre de colonnes égal le nombre de champs (double boucle)
Ensuite :
- créez un formulaire pour lister les régions
- un menu de sélection (
<select>
et<option>
) - chaque option doit être extraite de la base (table
regions
, champsinsee
etnom
)
- un menu de sélection (
- lors de la validation du formulaire, récupérez l’identifiant de la region pour modifier la requête SQL et ainsi n’afficher que les départements de cette région (utilisez le champ
region_insee
de la tabledepartements
) - enfin, ajoutez l’attribut
selected
sur la balise<option>
précédemment choisie
Voir plus bas :
- assurez-vous que vos requêtes ne soient pas soumises aux injections SQL
Sécurité - Injection SQL#
Dans le cas où l’on exécuterait une requête basée sur des données utilisateurs (récupérées dans l’URL par exemple), notre code est exposé à une faille de type injection SQL.
Démonstration d’une faille de type injection SQL
<?php
$results = mysqli_query($link, "SELECT * FROM departements WHERE id_region=" . $_GET['id_region']);
?>
Ici on sélectionne un département dont l’id
de région est l’id
passé dans l’URL. On aura donc une URL de type code.php?id_region=8
. Mais que se passe t’il si l’utilisateur modifie cette URL vers code.php?id=8 OR true; DROP DATABASE;
? Et bien, la requête sera exécutée ! O_o (en fonction des droits de l’utilisateur quand même)
Pour contrer cela, il faut alors utiliser le concept de requêtes préparées :
mysqli_prepare($link, $sql)
ou chaque paramètre de la requête SQL est remplacé par un?
mysqli_stmt_bind_param($requete, $types, $vars)
pour lier des variables dans notre requêtetypes
est une chaine de caractères qui définit le type pour chaque variables:"s"
pourstring
,"i"
pourinteger
,"ss"
pour deuxstring
etc.
mysqli_stmt_execute($requete)
pour exécuter la requêtemysqli_stmt_get_result($requete)
pour récupérer les résultats enmysqli_result
Utilisation de requêtes préparées
<?php
// requete preparee
$requete = mysqli_prepare($link, "SELECT * FROM departements WHERE id_region = ?");
// lie des donnees à la requete (dans l’ordre)
$id = $_GET['id_region'];
mysqli_stmt_bind_param($requete, "i", $id);
// execution
mysqli_stmt_execute($requete);
// recuperation des resultats
$results = mysqli_stmt_get_result($requete);
?>
Pour plus d’infos, voir la documentation officielle de la classe mysqli_stmt
.
Si vous utilisez PDO et Flight, voir le dernier exemple du tutoriel de Flight.
Postgres#
Si vous souhaitez vous connecter à une base de données de type PostgreSQL, voici les différentes fonctions en PHP :
<?php
// connexion
$link = pg_connect("host=<server> port=<port> dbname=<dbname> user=<user> password=<pass>");
// requete non sécurisée
$reponse = pg_query($link, "SELECT champ FROM table");
// requete sécurisée
$reponse = pg_query_params($link, "SELECT champ FROM table WHERE id = $1", [ $_GET['id'] ]);
// resultats en tableau associatif
$resultats = pg_fetch_all($reponse, PGSQL_ASSOC);
?>
Voir la liste de toutes les fonctions et exemples
Pour rappel, nécessite de configurer PHP (car l’extension Postgres n’est pas chargée par défaut)