Vous êtes sur la page 1sur 65

PDO : PHP Data Object

Achref El Mouelhi

Docteur de l’université d’Aix-Marseille


Chercheur en Programmation par contrainte (IA)
Ingénieur en Génie logiciel

elmouelhi.achref@gmail.com

28 juillet 2020

H & H: Research and Training 1 / 51


Introduction

PHP
Plusieurs extensions possibles pour se connecter à une BD
mysql
mysqli
I c

PDO
ELH
U
L MO
f E
chre
c A

H & H: Research and Training 2 / 51


Introduction

PHP
Plusieurs extensions possibles pour se connecter à une BD
mysql
mysqli
I c

PDO
ELH
U
L MO
f E
Quel choix ? !
A c hre
c
mysql
et mysqli sont utilisables seulement pour se connecter
à une base de données MySQL
PDO : une seule manière pour se connecter à n’importe quelle
base de données (Oracle, PostgreSQL, SQLITE...)

H & H: Research and Training 2 / 51


Introduction

PHP

PHP Data Object


I c

E H
L quelle base de
est une extension PHP pour accéder à n’importe
U
données
L MO
fournit une interface e
h r f E pour l’accès aux données
d’abstraction
A c orientée objet
c
est une interface

H & H: Research and Training 3 / 51


Introduction

PHP
Avant de commencer, voici le script SQL qui permet de créer la base de
données utilisée dans ce cours

CREATE DATABASE courspdo;

USE courspdo;
I c

E LH
CREATE TABLE personne(
num INT PRIMARY KEY AUTO_INCREMENT, OU
L M
nom VARCHAR(30),
prenom VARCHAR(30)
ref E
);
c h
c A
SHOW TABLES;

INSERT INTO personne (nom, prenom) VALUES ("Wick", "John"),


("Dalton", "Jack");

SELECT * FROM personne;

H & H: Research and Training 4 / 51


Introduction

PHP

Pour activer PDO avec WAMP, il faut


I c

cliquer sur WAMP
EL H
O U
L MExtensions
aller dans le menu PHP et choisir PHP
cocher pdo mysql ref
E
A h
cémarrage des services

attendrecle red

H & H: Research and Training 5 / 51


Introduction

PHP

Trois étapes
I c

E L H
Établir la connexion avec la base de donn
O U ées
L M
r e f Eêtes SQL
Créer et préparer des requ

A chérer le résultat de la requête


Exécuter et récup
c

H & H: Research and Training 6 / 51


Connexion à la BD

PHP
Syntaxe

<?php
maBase = new PDO (DSN, nomUtilisateur, motDePasse, [options]);
?>

I c

ELH
U
L MO
f E
chre
c A

H & H: Research and Training 7 / 51


Connexion à la BD

PHP
Syntaxe

<?php
maBase = new PDO (DSN, nomUtilisateur, motDePasse, [options]);
?>

I c

ELH
U
DSN : Data Source Name
L MO
f E
hre
mysql:host=adresse;dbname=nomBD;port=numPort;charset=encodage

A c
c
host :
localhost

dbname : courspdo

port : 3306 ou 3308

charset : utf8

H & H: Research and Training 7 / 51


Connexion à la BD

PHP

Exemple
$username = "root";
$password = ’’;
I c

utf8’;
ELH
$dsn = ’mysql:host=localhost;dbname=courspdo;port=3308;charset=

U
MO
$db = new PDO($dsn, $username, $password);

f E L
chre
c A

H & H: Research and Training 8 / 51


Connexion à la BD

PHP

Exemple
$username = "root";
$password = ’’;
I c

utf8’;
ELH
$dsn = ’mysql:host=localhost;dbname=courspdo;port=3308;charset=

U
MO
$db = new PDO($dsn, $username, $password);

f E L
chre
c A

Une exception à capturer
le constructeur de PDO peut lancer une exception s’il ne peut se
connecter à la base

H & H: Research and Training 8 / 51


Connexion à la BD

PHP

Exemple

try {
I c

$username = "root";
ELH
$password = ’’;
U
MO
$dsn = ’mysql:host=localhost;dbname=courspdo;port=3308;
L
charset=utf8’;
f E
hre
$db = new PDO($dsn, $username, $password);
c
c A
} catch (PDOException $e) {

}
echo ’Erreur : ’ . $e->getMessage();

H & H: Research and Training 9 / 51


Connexion à la BD

PHP

Pour avoir des messages d’erreur précis, on ajoute un quatrième paramètre au


constructeur de PDO

try {
I c

$username = "root";
ELH
U
MO
$password = ’’;
$dsn = ’mysql:host=localhost;dbname=courspdo;port=3308;
charset=utf8’;
f E L
hre
$db = new PDO($dsn, $username, $password, array(PDO::
c
c A
ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION));

} catch (PDOException $e) {
echo ’Erreur : ’ . $e->getMessage();
}

H & H: Research and Training 10 / 51


Connexion à la BD

PHP

Ou on peut l’ajouter avec le setter

try {
$username = "root";
I c

$password = ’’;
ELH
U
MO
$dsn = ’mysql:host=localhost;dbname=courspdo;port=3308;
charset=utf8’;

f E L
$db = new PDO($dsn, $username, $password);

hre
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION
c
c A
);

} catch (PDOException $e) {
echo ’Erreur : ’ . $e->getMessage();
}

H & H: Research and Training 11 / 51


Consultation de données

PHP

Pour exécuter une requête

se connecter à la base de données

utiliser l’objet connexion pour effectuer les requêtes

I c

ELH
U
L MO
f E
chre
c A

H & H: Research and Training 12 / 51


Consultation de données

PHP

Pour exécuter une requête

se connecter à la base de données

utiliser l’objet connexion pour effectuer les requêtes

I c

ELH
U
L MO
try {
f E
hre
$username = "root";
$password = ’’;
c
c A

$dsn = ’mysql:host=localhost;dbname=coursphdo;port=3308;charset=
utf8’;
$db = new PDO($dsn, $username, $password);
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$req = $db->query(’select * from personne’);
} catch (PDOException $e) {
echo ’Erreur : ’ . $e->getMessage();
}

H & H: Research and Training 12 / 51


Consultation de données

PHP
Afficher le résultat de la requête

Dans $req, on a le résultat de l’exécution de la requête SQL

Avec fetch() ou fetchAll(), on obtient le résultat sous forme d’un tableau

I c

ELH
U
L MO
f E
c hre
c A

H & H: Research and Training 13 / 51


Consultation de données

PHP
Afficher le résultat de la requête

Dans $req, on a le résultat de l’exécution de la requête SQL

Avec fetch() ou fetchAll(), on obtient le résultat sous forme d’un tableau

I c

try {
ELH
U
MO
$username = "root";
$password = ’’;

E L
$dsn = ’mysql:host=localhost;dbname=courspdo;port=3308;charset=utf8
f
hre
’;

c
$db = new PDO($dsn, $username, $password);

c A
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

$req = $db->query(’select * from personne’);
$res = $req->fetchAll();
foreach ($res as $key => $value) {
echo "$value[0] $value[1] $value[2] <br>";
}
} catch (PDOException $e) {
echo ’Erreur : ’ . $e->getMessage();
}

H & H: Research and Training 13 / 51


Consultation de données

PHP
Exemple avec fetch

try {
$username = "root";
$password = ’’;
$dsn = ’mysql:host=localhost;dbname=courspdo;port=3308;
I c

charset=utf8’;
ELH
U
MO
$db = new PDO($dsn, $username, $password);
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION
);
f E L
hre
$req = $db->query(’select * from personne’);
c
c A
while ($tuple = $req->fetch()) {

echo $tuple[’num’] . " " . $tuple[’nom’] . " ". $tuple[
’prenom’]. "<br>";
}
} catch (PDOException $e) {
echo ’Erreur : ’ . $e->getMessage();
}

H & H: Research and Training 14 / 51


Consultation de données

PHP
Fermer le curseur pour exécuter une autre requête

try {
$username = "root";
$password = ’’;
$dsn = ’mysql:host=localhost;dbname=courspdo;port=3308;
I c

charset=utf8’;
ELH
$db = new PDO($dsn, $username, $password);
U
MO
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION
L
);
f E
hre
$req = $db->query(’select * from personne’);
c
while ($tuple = $req->fetch()) {

c A

echo $tuple[’num’] . " " . $tuple[’nom’] . " ". $tuple[
’prenom’]. "<br>";
}
$req->closeCursor();
} catch (PDOException $e) {
echo ’Erreur : ’ . $e->getMessage();
}

H & H: Research and Training 15 / 51


Consultation de données

Pour terminer, on peut fermer la connexion


try {
$username = "root";
$password = ’’;
$dsn = ’mysql:host=localhost;dbname=courspdo;port=3308;charset=utf8
’;
$db = new PDO($dsn, $username, $password);
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$req = $db->query(’select * from personne’);
I c

while ($tuple = $req->fetch()) {
ELH
U
echo $tuple[’num’] . " " . $tuple[’nom’] . " ". $tuple[’prenom’

}
]. "<br>";
L MO
f E
hre
$req->closeCursor();
// pour fermer la connexion
c
c A
$db = null;
// ou ainsi
unset($db);
} catch (PDOException $e) {
echo ’Erreur : ’ . $e->getMessage();
}

H & H: Research and Training 16 / 51


Consultation de données

Pour terminer, on peut fermer la connexion


try {
$username = "root";
$password = ’’;
$dsn = ’mysql:host=localhost;dbname=courspdo;port=3308;charset=utf8
’;
$db = new PDO($dsn, $username, $password);
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$req = $db->query(’select * from personne’);
I c

while ($tuple = $req->fetch()) {
ELH
U
echo $tuple[’num’] . " " . $tuple[’nom’] . " ". $tuple[’prenom’

}
]. "<br>";
L MO
f E
hre
$req->closeCursor();
// pour fermer la connexion
c
c A
$db = null;
// ou ainsi
unset($db);
} catch (PDOException $e) {
echo ’Erreur : ’ . $e->getMessage();
}

Si on ne le fait pas explicitement, PHP fermera automatiquement la connexion lorsque le script


arrivera à la fin

H & H: Research and Training 16 / 51


Consultation de données

PHP
Mode de récupération des données (paramètres de fetch())

PDO::FETCH BOTH (par défaut) : retourne chaque ligne dans un tableau indexé
par les noms des colonnes ainsi que leurs numéros, en commençant à 0.

I c

PDO::FETCH ASSOC : retourne chaque ligne dans un tableau indexé par les

ELH
noms des colonnes comme elles sont retournées dans le jeu de résultats
U
MO
correspondant.

E L
PDO::FETCH NUM : retourne chaque ligne dans un tableau indexé par le numéro
f
hre
des colonnes en commençant de 0.
c
c A

PDO::FETCH OBJ : retourne chaque ligne dans un objet avec les noms de
propriétés correspondant aux noms des colonnes comme elles sont retournées
dans le jeu de résultats.

PDO::FETCH CLASS ou PDO::FETCH CLASSTYPE : retourne une nouvelle


instance de la classe demandée, liant les colonnes aux propriétés nommées
dans la classe.

H & H: Research and Training 17 / 51


Consultation de données

PHP
Exemple avec PDO::FETCH NUM

try {
$username = "root";
$password = ’’;

I c

$dsn = ’mysql:host=localhost;dbname=courspdo;port=3308;charset=utf8
’;
$db = new PDO($dsn, $username, $password);
ELH
U
MO
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

f E L
$req = $db->query(’select * from personne’);
$tuple = $req->setFetchMode(PDO::FETCH_NUM);

hre
while ($tuple = $req->fetch()) {
c
c A
echo $tuple[0] . " " . $tuple[1] . " ". $tuple[2]. "<br>";

}
$tuple[’prenom’]. "<br>";

$req->closeCursor();
$db = null;
} catch (PDOException $e) {
echo ’Erreur : ’ . $e->getMessage();
}

H & H: Research and Training 18 / 51


Consultation de données

PHP

On peut préciser le mode directement dans fetch

try {
$username = "root";
$password = ’’;
I c

$dsn = ’mysql:host=localhost;dbname=courspdo;port=3308;charset=utf8
’;
ELH
$db = new PDO($dsn, $username, $password);
U
L
$req = $db->query(’select * from personne’); MO
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

f E
hre
// $tuple = $req->setFetchMode(PDO::FETCH_NUM);
while ($tuple = $req->fetch(PDO::FETCH_NUM)) {
c
c A
echo $tuple[0] . " " . $tuple[1] . " ". $tuple[2]. "<br>";
}

$req->closeCursor();
$db = null;
} catch (PDOException $e) {
echo ’Erreur : ’ . $e->getMessage();
}

H & H: Research and Training 19 / 51


Consultation de données

PHP

Exemple avec PDO::FETCH OBJ

try {
$username = "root";
$password = ’’;
I c

$dsn = ’mysql:host=localhost;dbname=courspdo;port=3308;charset=utf8
’;
ELH
$db = new PDO($dsn, $username, $password);
U
L
$req = $db->query(’select * from personne’); MO
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

f E
hre
while ($tuple = $req->fetch(PDO::FETCH_OBJ)) {
echo $tuple->num . " " . $tuple->nom . " " . $tuple->prenom . "
c
c A
<br>";
}

$req->closeCursor();
$db = null;
} catch (PDOException $e) {
echo ’Erreur : ’ . $e->getMessage();
}

H & H: Research and Training 20 / 51


Requête paramétrée

PHP
Considérons la page formulaire.php

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Formulaire</title>
I c

</head>
ELH
<body>
U
MO
<form method=’post’ action=’test.php’>
<div>

f E L
nom : <input type=’text’ name=’nom’>
</div>
chre
c A
<div>


</div>
<div>
prenom : <input type=’text’ name=’prenom’>

<input type=’submit’ value=’connexion’>


</div>
</form>
</body>
</html>

H & H: Research and Training 21 / 51


Requête paramétrée

PHP
Le corps de la page test.php

try
{
$username = "root";
$password = ’’;
I c

’;
ELH
$dsn = ’mysql:host=localhost;dbname=courspdo;port=3308;charset=utf8

$db = new PDO($dsn, $username, $password);


U
MO
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
L
E
$req = $db->query(’select * from Personne where nom = \’’ . $_POST[
f
hre
’nom’] . ’\’and prenom = \’’ . $_POST[’prenom’] . ’\’’);
if ($req->fetch())
c
c A
echo "Bonjour";
else

echo "Vous n’êtes pas inscrit";
$db = null;
} catch (Exception $e) {
echo (’Erreur : ’ . $e->getMessage());
}
?>

H & H: Research and Training 22 / 51


Requête paramétrée

PHP
Injection SQL : faille XSS (cross-site scripting)

En saisissant un nom et un prénom qui existent dans la base, on peux se connecter.

Mais on peut aussi se connecter en saisissant des valeurs inexistantes

I c

ELH
U
L MO
f E
chre
c A

H & H: Research and Training 23 / 51


Requête paramétrée

PHP
Injection SQL : faille XSS (cross-site scripting)

En saisissant un nom et un prénom qui existent dans la base, on peux se connecter.

Mais on peut aussi se connecter en saisissant des valeurs inexistantes

I c

ELH
U
Exemple
L MO
f E
hre
Nom : un nom qui existe (Wick)

c
c A
Prénom : xxx ?’ or true !=’

H & H: Research and Training 23 / 51


Requête paramétrée

PHP
Injection SQL : faille XSS (cross-site scripting)

En saisissant un nom et un prénom qui existent dans la base, on peux se connecter.

Mais on peut aussi se connecter en saisissant des valeurs inexistantes

I c

ELH
U
Exemple
L MO
f E
hre
Nom : un nom qui existe (Wick)

c
c A
Prénom : xxx ?’ or true !=’

Solution

Des fonctions spéciales ou les requêtes préparées

H & H: Research and Training 23 / 51


Requête paramétrée

PHP

les fonctions spéciales

$nom connexion->quote($nom chaı̂ne) : désactive les quotes insérées


par l’utilisateur
I c
EL H
htmlspecialchars($nom chaı̂ne) : élimine les < et >. Pour récupérer la
U
chaı̂ne d’origine on peut utiliser htmlspecialchars decode().

strip tags($nom chaı̂ne) : supprime L MlesObalises HTML et PHP


h r e f lesEantislash d’une chaı̂ne de caractère.
c
stripcslashes : supprime
A
c
htmlentities($nom chaı̂ne) : remplace les ’ ” < > par leur code HTML
(&lt ;...). Pour récupérer la chaı̂ne d’origine on peut utiliser
html entity decode().

addcslashes() : ajoute des slashs devant des caractères mentionnés d’une


chaı̂ne de caractère.

H & H: Research and Training 24 / 51


Requête paramétrée

Une deuxième solution consiste à utiliser les requêtes préparées et le marqueur ?

try
{
$username = "root";
$password = ’’;
$dsn = ’mysql:host=localhost;dbname=courspdo;port=3308;charset=utf8
’;
$db = new PDO($dsn, $username, $password);
I c

ELH
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

U
$req = $db->prepare(’select * from Personne where nom = ? and

MO
prenom = ?’);

if ($req->fetch())
f E L
$req->execute(array($_POST[’nom’], $_POST[’prenom’]));

echo "Bonjour";
chre
c A
else

$db = null;
echo "Vous n’êtes pas inscrit";

} catch (Exception $e) {


echo (’Erreur : ’ . $e->getMessage());
}

H & H: Research and Training 25 / 51


Requête paramétrée

Une deuxième solution consiste à utiliser les requêtes préparées et le marqueur ?

try
{
$username = "root";
$password = ’’;
$dsn = ’mysql:host=localhost;dbname=courspdo;port=3308;charset=utf8
’;
$db = new PDO($dsn, $username, $password);
I c

EL
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
H
U
$req = $db->prepare(’select * from Personne where nom = ? and

MO
prenom = ?’);

if ($req->fetch())
f E L
$req->execute(array($_POST[’nom’], $_POST[’prenom’]));

echo "Bonjour";
chre
c A
else

$db = null;
echo "Vous n’êtes pas inscrit";

} catch (Exception $e) {


echo (’Erreur : ’ . $e->getMessage());
}

Attention à l’ordre des paramètres

H & H: Research and Training 25 / 51


Requête paramétrée

Une troisième solution consiste à utiliser le marqueur nominatif :

try {
$username = "root";
$password = ’’;
$dsn = ’mysql:host=localhost;dbname=courspdo;port=3308;charset=utf8
’;
$db = new PDO($dsn, $username, $password);
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
I c

ELH
$req = $db->prepare(’select * from Personne where nom = :nom and
prenom = :prenom’);
U
$req->execute(array(
’nom’ => $_POST[’nom’],
L MO
f E
hre
’prenom’ => $_POST[’prenom’]
));
c
c A
if ($req->fetch())

else
echo "Bonjour";

echo "Vous n’êtes pas inscrit";


$db = null;
} catch (Exception $e) {
echo (’Erreur : ’ . $e->getMessage());
}

H & H: Research and Training 26 / 51


Requête paramétrée

PHP
Une quatrième solution consiste à utiliser le marqueur nominatif : et la méthode
bindValue()
try {
$username = "root";
$password = ’’;
c

$dsn = ’mysql:host=localhost;dbname=courspdo;port=3308;charset=utf8
I
’;
$db = new PDO($dsn, $username, $password);
ELH
U
MO
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$req = $db->prepare(’select * from Personne where nom = :nom and
prenom = :prenom’);
f E L
hre
$req->bindValue(’:nom’, $_POST[’nom’]);

c
$req->bindValue(’:prenom’, $_POST[’prenom’]);

c A
$req->execute();

if ($req->fetch())
echo "Bonjour";
else
echo "Vous n’êtes pas inscrit";
$db = null;
} catch (Exception $e) {
echo (’Erreur : ’ . $e->getMessage());
}

H & H: Research and Training 27 / 51


Requête paramétrée

PHP

I c

Attention
ELH
U
bindValue() copie la valeur
L MO
f E
hre
bindParam() copie la référence
c
c A

H & H: Research and Training 28 / 51


Requête paramétrée

Limite de bindValue()

$nom = ’wick’;
$prenom = ’john’
$req = $db->prepare(’select * from Personne where nom = :nom and prenom
= :prenom’);
$req->bindValue(’:nom’, $nom);
$req->bindValue(’:prenom’, $prenom);
$nom = ’travolta’;
I c

$req->execute();
// la requête sera exécutée avec les valeurs wick et john
ELH
U
L MO
f E
chre
c A

H & H: Research and Training 29 / 51


Requête paramétrée

Limite de bindValue()

$nom = ’wick’;
$prenom = ’john’
$req = $db->prepare(’select * from Personne where nom = :nom and prenom
= :prenom’);
$req->bindValue(’:nom’, $nom);
$req->bindValue(’:prenom’, $prenom);
$nom = ’travolta’;
I c

$req->execute();
// la requête sera exécutée avec les valeurs wick et john
ELH
U
L MO
f E
hre
Exemple avec bindParam()

c
c A
$nom = ’wick’;
$prenom = ’john’

$req = $db->prepare(’select * from Personne where nom = :nom and prenom
= :prenom’);
$req->bindParam(’:nom’, $nom);
$req->bindParam(’:prenom’, $prenom);
$nom = ’travolta’;
$req->execute();
// la requête sera exécutée avec les valeurs travolta et john

H & H: Research and Training 29 / 51


Requête paramétrée

PHP
Le type de la valeur PHP ne dicte pas le type SQL, mais c’est le troisième paramètre
(optionnel) de bindValue
try {
$username = "root";
$password = ’’;

c

$dsn = ’mysql:host=localhost;dbname=courspdo;port=3308;charset=utf8
I
’;
$db = new PDO($dsn, $username, $password);
ELH
U
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

MO
$req = $db->prepare(’select * from Personne where nom = :nom and
L
prenom = :prenom’);
f E
hre
$req->bindValue(’:nom’, $_POST[’nom’], PDO::PARAM_STR);

c
$req->bindValue(’:prenom’, $_POST[’prenom’], PDO::PARAM_STR);

c A
$req->execute();

if ($req->fetch())
echo "Bonjour";
else
echo "Vous n’êtes pas inscrit";
$db = null;
} catch (Exception $e) {
echo (’Erreur : ’ . $e->getMessage());
}

H & H: Research and Training 30 / 51


Requête paramétrée

PHP

I c

H
EL le type
U
Pour consulter la liste de constantes PDO spécifiant

L MO
https://www.php.net/manual/fr/pdo.constants.php

h r e fE
A c
c

H & H: Research and Training 31 / 51


Écriture de données

PHP
Insérer des données

try {
$username = "root";
$password = ’’;

’;
I c
$dsn = ’mysql:host=localhost;dbname=courspdo;port=3308;charset=utf8

$db = new PDO($dsn, $username, $password);
ELH
U
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$nom = $_POST[’nom’];
$prenom = $_POST[’prenom’];
L MO
f E
$res = $db->exec("INSERT INTO Personne (nom, prenom) VALUES(’$nom
’,’$prenom’)");
chre
c A
echo $res ? "tuple inséré" : "problème d’insertion";
$db = null;

} catch (Exception $e) {
echo (’Erreur : ’ . $e->getMessage());
}

H & H: Research and Training 32 / 51


Écriture de données

PHP
Insérer des données

try {
$username = "root";
$password = ’’;

’;
I c
$dsn = ’mysql:host=localhost;dbname=courspdo;port=3308;charset=utf8

$db = new PDO($dsn, $username, $password);
ELH
U
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$nom = $_POST[’nom’];
$prenom = $_POST[’prenom’];
L MO
f E
$res = $db->exec("INSERT INTO Personne (nom, prenom) VALUES(’$nom
’,’$prenom’)");
c hre
c A
echo $res ? "tuple inséré" : "problème d’insertion";
$db = null;

} catch (Exception $e) {
echo (’Erreur : ’ . $e->getMessage());
}

$res contient le nombre de tuples insérés

H & H: Research and Training 32 / 51


Écriture de données

PHP
Insérer des données avec les requêtes préparées

try {
$username = "root";
$password = ’’;

c

$dsn = ’mysql:host=localhost;dbname=courspdo;port=3308;charset=utf8
I
’;
$db = new PDO($dsn, $username, $password);
ELH
U
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$nom = $_POST[’nom’];
L MO
$prenom = $_POST[’prenom’];
f E
hre
$req = $db->prepare("INSERT INTO Personne (nom, prenom) VALUES(:nom
,:prenom)");
c
c A
$req->bindValue(":nom", $nom);

$req->bindValue(":prenom", $prenom);
$res = $req->execute();
echo $res ? "tuple inséré" : "problème d’insertion";
$db = null;
} catch (Exception $e) {
echo (’Erreur : ’ . $e->getMessage());
}

H & H: Research and Training 33 / 51


Écriture de données

PHP
Pour récupérer l’identifiant de la personne ajoutée
try {
$username = "root";
$password = ’’;
$dsn = ’mysql:host=localhost;dbname=courspdo;port=3308;charset=utf8
’;
I c

$db = new PDO($dsn, $username, $password);

ELH
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
U
MO
$nom = $_POST[’nom’];
$prenom = $_POST[’prenom’];

E L
$req = $db->prepare("INSERT INTO Personne (nom, prenom) VALUES(:nom
f
hre
,:prenom)");

c
$req->bindValue(":nom", $nom);

c A
$req->bindValue(":prenom", $prenom);

$res = $req->execute();
$id = $db->lastInsertId();
echo $res ? "tuple inséré avec identifiant $id" : "problème d’
insertion";
$db = null;
} catch (Exception $e) {
echo (’Erreur : ’ . $e->getMessage());
}

H & H: Research and Training 34 / 51


Écriture de données

PHP

I c
E LH
U
MOet la modification
De même pour la suppression
L
h r e fE
A c
c

H & H: Research and Training 35 / 51


Transactions

PHP

Une transaction
Un ensemble de requêtes SQL
I c

Exécutée en bloc (soit tout, soit rien)
ELH
U
L MO
h r e fE
A c
c

H & H: Research and Training 36 / 51


Transactions

PHP

Une transaction
Un ensemble de requêtes SQL
I c

Exécutée en bloc (soit tout, soit rien)
ELH
U
L MO
h r e fE
A c bancaire
Exemple : un virement
c
Un retrait d’un premier compte
Un versement vers un deuxième

H & H: Research and Training 36 / 51


Transactions

PHP

Comment ça marche ?

À la fin de chaque transaction, on peut soit valider (commit), soit


I c

annuler (rollback), même en cas de réussite de toutes les
requêtes.
EL H
U
Osera annulée et les
M
Si une requête échoue, la transaction
L
f
changements ne seront pas
r e E validés.
A ch requête est considérée comme une
Par défaut, chaque
c : validé si la requête n’échoue pas.
transaction

H & H: Research and Training 37 / 51


Transactions

PHP

Comment ça marche ?

À la fin de chaque transaction, on peut soit valider (commit), soit


I c

annuler (rollback), même en cas de réussite de toutes les
requêtes.
EL H
U
Osera annulée et les
M
Si une requête échoue, la transaction
L
f
changements ne seront pas
r e E validés.
A ch requête est considérée comme une
Par défaut, chaque
c : validé si la requête n’échoue pas.
transaction

Non nécessaire si elle concerne une seule requête

H & H: Research and Training 37 / 51


Transactions

Transaction : syntaxe
try {
$username = "root";
$password = ’’;
$dsn = ’mysql:host=localhost;dbname=courspdo;port=3308;charset=utf8
’;
$db = new PDO($dsn, $username, $password);

c

$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$db->beginTransaction();
I
$nom = $_POST[’nom’];
ELH
$prenom = $_POST[’prenom’];
U
,:prenom)");
L MO
$req = $db->prepare("INSERT INTO Personne (nom, prenom) VALUES(:nom

f E
hre
$req->bindValue(":nom", $nom);
$req->bindValue(":prenom", $prenom);
c
c A
$res = $req->execute();

$id = $db->lastInsertId();
$db->commit();
echo $res ? "tuple inseré avec identifiant $id" : "problème d’
insertion";
$db = null;
} catch (Exception $e) {
$db->rollback();
echo (’Erreur : ’ . $e->getMessage());
}
H & H: Research and Training 38 / 51
POO et PDO

PHP
Créons une classe Personne (entité) dans un répertoire models

class Personne
{
private $num;
private $nom;
private $prenom;
I c

ELH
U
public function __construct(int $num, string $nom, string $prenom)

MO
{
$this->setNum($num);
$this->nom = $nom;
f E L
hre
$this->prenom = $prenom;
c
c A
}


// + les getters + setters

public function __toString(): string


{
return $this->num . " " . $this->nom . " " . $this->prenom;
}
}

H & H: Research and Training 39 / 51


POO et PDO

PHP
Utilisation de la classe pour afficher les tuples

try {
$username = "root";
$password = ’’;

’;
I c
$dsn = ’mysql:host=localhost;dbname=courspdo;port=3308;charset=utf8

$db = new PDO($dsn, $username, $password);
ELH
U
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$req = $db->query(’select * from Personne’);

L
while($res = $req->fetch(PDO::FETCH_NUM)){ MO
f E
$perso = new Personne($res[0], $res[1], $res[2]);
echo $perso;
chre
c A
}
$db = null;
unset($db);
} catch (PDOException $e) {
echo ’Erreur : ’ . $e->getMessage();
}

H & H: Research and Training 40 / 51


POO et PDO

PHP
Utilisation de la classe pour afficher les tuples

try {
$username = "root";
$password = ’’;

’;
I c
$dsn = ’mysql:host=localhost;dbname=courspdo;port=3308;charset=utf8

$db = new PDO($dsn, $username, $password);
ELH
U
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$req = $db->query(’select * from Personne’);

L
while($res = $req->fetch(PDO::FETCH_NUM)){ MO
f E
$perso = new Personne($res[0], $res[1], $res[2]);
echo $perso;
c hre
c A
}
$db = null;
unset($db);
} catch (PDOException $e) {
echo ’Erreur : ’ . $e->getMessage();
}

Il faut faire attention à l’ordre des attributs (et des colonnes)

H & H: Research and Training 40 / 51


POO et PDO

PHP
Ajoutons la méthode hydrate($tuple) dans la classe Personne

public function __construct(array $tuple)


{
if (count($tuple))
$this->hydrate($tuple);
I c

}
EL H
U
MO
public function hydrate(array $tuple)
L
{
foreach ($tuple as e
h r f E=> $value) {
$key
A c : uppercase first letter
// ucfirst()
c
$method = ’set’ . ucfirst($key);
if (method_exists($this, $method)) {
$this->$method($value);
}
}
}

H & H: Research and Training 41 / 51


POO et PDO

PHP
Pour tester
try {
$username = "root";
$password = ’’;

c

$dsn = ’mysql:host=localhost;dbname=courspdo;port=3308;
I
charset=utf8’;
$db = new PDO($dsn, $username, $password);
ELH
U
MO
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION
);
f E L
$req = $db->query(’select * from Personne’);
hre
while($res = $req->fetch(PDO::FETCH_ASSOC)){
c
c A
$perso = new Personne($res);

}

echo $perso;

$db = null;
unset($db);
} catch (PDOException $e) {
echo ’Erreur : ’ . $e->getMessage();
}

H & H: Research and Training 42 / 51


POO et PDO

PHP

I c

H
Deuxième solution avec un constructeur sans paramètre
EL
U
MO
public function __construct()
{
fE L
}
c h r e
c A

H & H: Research and Training 43 / 51


POO et PDO

PHP
Pour tester, on utilise le mode PDO::FETCH CLASS
try {
$username = "root";
$password = ’’;

c

$dsn = ’mysql:host=localhost;dbname=courspdo;port=3308;
I
charset=utf8’;
$db = new PDO($dsn, $username, $password);
ELH
U
MO
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION
);
f E L
$req = $db->query(’select * from Personne’);
hre
$personnes = $req->fetchAll(PDO::FETCH_CLASS, ’Personne’);
c
c A
foreach ($personnes as $personne) {

}

echo $personne->getNom() . "<br>";

$db = null;
unset($db);
} catch (PDOException $e) {
echo ’Erreur : ’ . $e->getMessage();
}

H & H: Research and Training 44 / 51


Restructuration du code

PHP

Organisation du code

Il faut mettre toutes les données (url, nomUtilisateur,


I c

ELH
motDePasse...) relatives à notre connexion dans une classe
connexion U
L MO
E
Pour chaque table de la base de données, on crée une entité
f
hre
ayant comme attributs les colonnes de cette table
c
c A

Il faut mettre tout le code correspondant à l’accès aux données
(de la base de données) dans des nouvelles classes ”Manager”
(qui constitueront la couche DAO : Data Access Object)

H & H: Research and Training 45 / 51


Restructuration du code

La classe Connection

class Connection
{
private static $db = null;
private static $instance = null;
const DB_USER = ’root’;
const DB_PASSWORD = ’’;
const DB_HOST = ’localhost’;
I c

const DB_NAME = ’courspdo’;
const DBMS_PORT = 3308;
ELH
U
private function __construct()
L MO
{
f E
hre
try {
c
c A
$dsn = ’mysql:dbname=’ . self::DB_NAME . ’;host=’ . self::


DB_HOST . ’;port=’ . self::DBMS_PORT;
self::$db = new PDO($dsn, self::DB_USER, self::DB_PASSWORD);
self::$db->setAttribute( PDO::ATTR_ERRMODE, PDO::
ERRMODE_EXCEPTION);
} catch (PDOException $e) {
echo ’Erreur : ’ . $e->getMessage();
}
}

H & H: Research and Training 46 / 51


Restructuration du code

PHP

La classe Connection (suite)


public static function getInstance()
I c

{
ELH
U
MO
if (self::$instance == null) {

f E L
self::$instance = new Connection();

hre
}
c
c A
return self::$db;

}
}

H & H: Research and Training 47 / 51


Restructuration du code

PHP

La classe Personne
class Personne
{
private $num;
I c

private $nom;
ELH
U
MO
private $prenom;

f E L
hre
public function __construct()
c
c A
{
}
// + getters + setters + __toString

H & H: Research and Training 48 / 51


Restructuration du code

PHP
La classe PersonneManager définie dans un répertoire dao
class PersonneManager
{
private $db = null;

public function __construct()


I c

{
$this->db = Connection::getInstance();
ELH
U
MO
}

E L
public function save(Personne $personne): int
f
hre
{

c
$req = $this->db->prepare(’INSERT INTO personne (nom, prenom)

c A
VALUES (:nom, :prenom)’);

$req->bindValue(’:nom’, $personne->getNom(), PDO::PARAM_STR);
$req->bindValue(’:prenom’, $personne->getPrenom(), PDO::
PARAM_STR);
$req->execute();
return $this->db->lastInsertId();
}
// + les autres méthodes
}

H & H: Research and Training 49 / 51


Restructuration du code

PHP

Pour tester toutes ces classes dans test.php


$nom = $_POST[’nom’];
$prenom = $_POST[’prenom’];
I c

$dao = new PersonneManager(); ELH
U
L MO
h r fE
$personne = new Personne();
e
$personne->setNom($nom):
A c
$personne->setPrenom($prenom):
c
$res = $dao->save($personne);
echo $res ? "tuple inséré avec identifiant $res" : "
problème d’insertion";

H & H: Research and Training 50 / 51


Restructuration du code

PHP

Remarque

I c

N’oubliez pas d’implémenter les quatre autres méthodes de la classe
PersonneManager
ELH
U
findAll()
L MO
f E
findById()
chre
update() c A

remove()

H & H: Research and Training 51 / 51

Vous aimerez peut-être aussi