Base de données avec PDO et Composer
Ce que tu vas apprendre
- Te connecter à une base de données avec PDO et lire des lignes.
- Écrire des requêtes préparées pour empêcher l'injection SQL.
- Installer des bibliothèques et charger tes classes avec Composer.
PDO : un accès unique aux bases
PDO (PHP Data Objects) est l'interface standard de PHP pour parler à une base de données. Le même code fonctionne avec plusieurs systèmes ; seule l'adresse de connexion change.
Pour rester simple, ce chapitre utilise SQLite, une base stockée dans un seul fichier, sans serveur à installer. L'extension SQLite de PDO doit être activée dans ton installation de PHP.
Se connecter
<?php
declare(strict_types=1);
$pdo = new PDO("sqlite:recettes.db", null, null, [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
]);
Le premier argument est le DSN, qui indique le type de base et sa position. Les deux null sont l'utilisateur et le mot de passe, inutiles avec SQLite.
Les deux options règlent le comportement : en cas d'erreur SQL, PHP lève une exception visible au lieu de se taire, et chaque ligne est renvoyée sous forme de tableau associatif.
Créer une table
<?php
$pdo->exec("
CREATE TABLE IF NOT EXISTS recettes (
id INTEGER PRIMARY KEY AUTOINCREMENT,
titre TEXT NOT NULL,
duree INTEGER NOT NULL
)
");
exec exécute une requête fixe, sans donnée venue de l'extérieur.
L'injection SQL
Voici ce qu'il ne faut jamais écrire :
<?php
// DANGEREUX
$sql = "SELECT * FROM recettes WHERE titre = '" . $_GET["titre"] . "'";
Si le visiteur envoie ' OR '1'='1, la requête devient vraie pour toutes les lignes. Avec d'autres textes, il peut lire d'autres tables ou tout effacer. C'est une injection SQL : la donnée saisie est interprétée comme du code SQL.
La requête préparée
Une requête préparée sépare la requête, envoyée d'abord avec des emplacements vides, des valeurs, transmises ensuite. La base ne confond plus jamais une valeur avec du SQL.
<?php
$stmt = $pdo->prepare("SELECT * FROM recettes WHERE duree <= :max");
$stmt->execute(["max" => 45]);
$rapides = $stmt->fetchAll();
:max est un emplacement nommé. execute le remplit avec la valeur du tableau. fetchAll renvoie toutes les lignes ; fetch n'en renvoie qu'une.
Ajouter une ligne
Voici l'enregistrement qui complète le formulaire du chapitre précédent :
<?php
$stmt = $pdo->prepare(
"INSERT INTO recettes (titre, duree) VALUES (:titre, :duree)"
);
$stmt->execute(["titre" => $titre, "duree" => $dureeNombre]);
$id = $pdo->lastInsertId();
lastInsertId donne l'identifiant de la ligne qui vient d'être créée. Le résultat s'affiche ensuite avec foreach, en pensant à htmlspecialchars.
Composer : le gestionnaire de dépendances
Composer installe les bibliothèques PHP dont ton projet a besoin et charge tes propres classes. Il se télécharge sur getcomposer.org. Dans ton dossier de projet :
composer init
composer require monolog/monolog
La première commande crée composer.json, qui décrit le projet. La seconde télécharge une bibliothèque dans le dossier vendor/ et l'inscrit dans le fichier.
L'autoload PSR-4
Plutôt que d'écrire un require pour chaque fichier, Composer sait charger une classe à partir de son nom. On associe un espace de noms à un dossier :
{
"autoload": {
"psr-4": { "App\\": "src/" }
}
}
Avec cette règle, la classe App\Recette se trouve dans src/Recette.php. Après avoir modifié cette section, régénère l'autoloader :
composer dump-autoload
Dans ton point d'entrée, une seule ligne suffit ensuite :
<?php
require __DIR__ . "/vendor/autoload.php";
use App\Recette;
$r = new Recette("Crêpes", 30);
vendor/ dans ton .gitignore. Il se reconstruit avec composer install à partir de composer.json et composer.lock.Étapes suivantes
Tu sais maintenant afficher, recevoir et enregistrer des données de façon sûre. Pour aller plus loin, tu peux :
- ranger l'accès à la base dans une classe, par exemple
RecetteRepository; - ajouter des mots de passe hachés avec
password_hash; - découvrir un framework comme Laravel ou Symfony, qui reposent sur Composer.
À retenir
- PDO est l'interface standard de PHP vers les bases de données ; le DSN
sqlite:fichier.dbdésigne une base SQLite. - Active
PDO::ERRMODE_EXCEPTIONpour que les erreurs SQL soient signalées. - Ne construis jamais du SQL en collant une valeur utilisateur : utilise
preparepuisexecute. fetchAllrenvoie toutes les lignes,fetchune seule.- Composer installe les bibliothèques (
composer require) dansvendor/. - L'autoload PSR-4 relie un espace de noms à un dossier ;
require "vendor/autoload.php"suffit à tout charger.
Pour aller plus loin
Sources officielles
Ensuite
- Projet
- Lignes de code
- Niveau
- Sous-sol
- Appartement
- PHP
- Pièce
- 6/7
- Plan n°
- php/06.pdo-et-composer