Vous êtes sur la page 1sur 4

PHP Base de donnes PDO

PDO

PDO (PHP Data Objects) est une interface pour accder une base de
Dveloppement Web 2 donnes depuis PHP. Elle gre la connexion, lenvoie des requtes, la
dconnexion la base de donnes. Elle permet de changer plus facilement
de systme de gestion de bases de donnes.
Bertrand Estellon Ouverture de la base :
Aix-Marseille Universit <?
$dbHost = $_SERVER['dbHost']; $dbBd = $_SERVER['dbBd'];
$dbPass = $_SERVER['dbPass']; $dbLogin = $_SERVER['dbLogin'];
April 1, 2014 $url = 'mysql:host='.$dbHost.';dbname='.$dbBd;
$db = new PDO($url, $dbLogin, $dbPass);
if (!$db) die("impossible d'ouvrir la base de donnes.");
$this->createDataBase();
?>

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
.. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. ..
Bertrand Estellon (AMU) Dveloppement Web 2 April 1, 2014 1 / 436 Bertrand Estellon (AMU) Dveloppement Web 2 April 1, 2014 164 / 436
PHP Base de donnes Les requtes et fonctions utiles PHP Base de donnes Les requtes et fonctions utiles

PDO Injections SQL


Une fois linstance de PDO construite, vous eectuez des requtes avec : Le code suivant :
$db->exec($request) : pour modier la base de donnes <?
$nickname = 'aa"; DELETE FROM users; '.
$db->query($request) : pour extraire des donnes de la base 'SELECT * FROM users WHERE nickname="';
$password = "truc";
Exemples : $res = $db->exec('UPDATE users SET password="'.
md5($password).'" WHERE nickname="'.$nickname.'";');
<?
?>
$db->exec("CREATE TABLE IF NOT EXISTS users (".
" nickname char(20),".
" password char(50)".
excute la requte SQL suivante :
");"); UPDATE users SET password="...." WHERE nickname="aa";
?> DELETE FROM users;
<? SELECT * FROM users WHERE nickname="";
$res = $db->exec('UPDATE users SET password="'.
md5($password).'" WHERE nickname="'.$nickname.'";'); Protection contre les injections SQL :
echo "nombre de lignes modifiees = $res"; <?
?> $r = $db->prepare('UPDATE users SET password = ? '.
<? 'WHERE nickname = ?');
$res = $db->query("select nickname from users;"); $r->execute(array(md5($password), $nickname));
?> . . . . . . . . . . . . . . . . . . . .
?> . . . . . . . . . . . . . . . . . . . .
.. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. ..
Bertrand Estellon (AMU) Dveloppement Web 2 April 1, 2014 165 / 436 Bertrand Estellon (AMU) Dveloppement Web 2 April 1, 2014 166 / 436
PHP Base de donnes Les requtes et fonctions utiles PHP Base de donnes Les requtes et fonctions utiles

PDO PDO
Pour faire une requte SQL :
Pour mettre toutes les lignes dans un tableau :
<?
$res = $db->query("select * from sondages"); <?
var_dump($res); $res = $db->query("select * from sondages");
/* affiche 'object(PDOStatement)#2 (1) { $lignes = !+$res->fetchAll();+!
["queryString"]=> string(19) "select * from sondages" }' */ foreach ($lignes as $ligne) {
?> echo $ligne['createur'].
" pose la question : ".
Pour connatre le nombre de lignes : $ligne['question']."\n";
}
<? echo "nombre de lignes : ".!+$res->rowCount()+!."\n"; ?> ?>

Pour parcourir les lignes : Voir aussi, dans la classe PDOStatement, les mthodes:
<?
$res = $db->query("select * from sondages");
bindColumn : attache une variable une colonne
while ($ligne = !+$res->fetch()+!) { errorInfo : information derreur
echo $ligne['createur'].
" pose la question : ". fetchColumn : rcupre la valeur dans une colonne donne
$ligne['question']."\n";
} closeCursor : ferme le curseur
?> . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
.. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. ..
Bertrand Estellon (AMU) Dveloppement Web 2 April 1, 2014 167 / 436 Bertrand Estellon (AMU) Dveloppement Web 2 April 1, 2014 168 / 436
PHP Base de donnes Les requtes et fonctions utiles PHP Base de donnes Les requtes et fonctions utiles

PDO Base de donnes du projet


Voir aussi, dans la classe PDO, les mthodes:
beginTransaction : dmarre une transaction
commit : valide une transaction Les trois tables utilises dans le projet :
rollback : annule une transaction
users(nickname char(20), password char(50));
errorInfo : Retourne les informations associes lerreur
errorCode : Retourne le SQLSTATE associ avec la dernire opration surveys(id integer primary key autoincrement,
prepare : Prpare une requte lexcution et retourne un objet owner char(20), question char(255));
quote : Protge une chane pour lutiliser dans une requte SQL PDO
responses(id integer primary key autoincrement,
<? id_survey integer,
$string = 'Chaine \' particulire'; title char(255),
print "non chappe : $string\n"; count integer);
print "chappe :" . $bd->quote($string) . "\n";
?>

Chaine non chappe : Chaine particulire


Chaine chappe : Chaine particulire ..
.
..
.
..
. . . . . . . . . . . . .
.. .. .. .. .. .. .. .. .. .. .. .. ..
.
..
.
..
.
..
.
..
.
..
.
..
.
..
. . . . . . . . . . . . .
.. .. .. .. .. .. .. .. .. .. .. .. ..
.
..
.
..
.
..
.
..
.

Bertrand Estellon (AMU) Dveloppement Web 2 April 1, 2014 169 / 436 Bertrand Estellon (AMU) Dveloppement Web 2 April 1, 2014 170 / 436
PHP Base de donnes Les requtes et fonctions utiles PHP Base de donnes Les requtes et fonctions utiles

Exemple : sauvegarde dun sondage La classe Database


<?
public function saveSurvey(&$survey) { <? class Database {
$this->connection->beginTransaction(); private $connection;

$query = $this->connection->prepare("INSERT INTO surveys(owner,question)". public function __construct() { ... }


"VALUES (?,?)");
if ($query===false) { $this->connection->rollback(); return false; } public function checkPassword($nickname, $password) { ... }
public function addUser($nickname, $password) { ... }
$r = $query->execute(array($survey->getOwner(), $survey->getQuestion())); public function updateUser($nickname, $password) { ... }
if ($r === false) { $this->connection->rollback(); return false; } public function saveSurvey(&$survey) { ... }
public function loadSurveysByOwner($owner) { ... }
$id = $this->connection->lastInsertId(); public function loadSurveysByKeyword($keyword) { ... }
$survey->setId($id); public function vote($id) { ... }

$responses = &$survey->getResponses(); private function createDataBase() { ... }


foreach ($responses as &$response) { private function checkNicknameValidity($nickname) { ... }
if ($this->saveResponse($response)===false) { private function checkPasswordValidity($password) { ... }
$this->connection->rollback(); return false; private function checkNicknameAvailability($nickname) { ... }
} private function saveResponse(&$response) { ... }
} private function loadSurveys($arraySurveys) { ... }
$this->connection->commit(); return true; private function loadResponses($survey, $arrayResponses) { ... }
} } ?>
?> . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
.. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. ..
Bertrand Estellon (AMU) Dveloppement Web 2 April 1, 2014 171 / 436 Bertrand Estellon (AMU) Dveloppement Web 2 April 1, 2014 172 / 436
PHP Base de donnes Mapping objet-relationnel (ORM) PHP Base de donnes Mapping objet-relationnel (ORM)

Mapping objet-relationnel (ORM) Redbean Introduction


Les besoins : Initialisation de la connexion la base de donnes :
Sauvegarde simple des objets en base de donnes : <?
<? $dbHost = $_SERVER['dbHost']; $dbBd = $_SERVER['dbBd'];
$user = new User(); $dbPass = $_SERVER['dbPass']; $dbLogin = $_SERVER['dbLogin'];
$user->nickname = "bob"; $url = 'mysql:host='.$dbHost.';dbname='.$dbBd;
$user->password = md5("truc"); R::setup($url, $dbLogin, $dbPass);
$user->save(); ?>
?>
Pour vider la base de donnes :

Cration automatique des tables;
<?
Chargement des objets;
R::nuke();
Gestion des relations entre les objets/enregistrements; ?>
...
Cration et sauvegarde dun bean :
Quelques solutions en PHP : <?
Propel $user = R::dispense('user');
$user->nickname = $nickname;
Doctrine
$user->password = $password;
Redbean R::store($user);
?>
... . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
.. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. ..
Bertrand Estellon (AMU) Dveloppement Web 2 April 1, 2014 173 / 436 Bertrand Estellon (AMU) Dveloppement Web 2 April 1, 2014 174 / 436
PHP Base de donnes Mapping objet-relationnel (ORM) PHP Base de donnes Mapping objet-relationnel (ORM)

Redbean Chargement des beans Redbean One-to-many


Chargement dun bean partir de son identiant :
<? Association one-to-many entre les sondages et les rponses :
$user = R::load('user', $_SESSION['id']); <?
/* retourne NULL si le bean n'a pas t trouv. */ $survey = R::dispense('survey');
?> $survey->owner = $_SESSION['id'];
$survey->question = $question;
Charger un bean dans la base de donnes partir dune requte :
<? $survey-> ownResponse = array();
$user = R::findOne('user', 'nickname = ? AND password = ?', foreach ($titles as $title) {
array($nickname, $password)); $response = R::dispense('response');
/* retourne NULL si le bean n'a pas t trouv. */ $response->title = $title;
?> $response->count = 0;
$survey->ownResponse[] = $response;
Charger plusieurs beans : /* Le nom du champ est important ! */
}
<?
$surveys = R::find('survey', 'question like ?', R::store($survey); /* Tout est sauv */
array('%'.$keyword.'%')); ?>
/* retourne un tableau. */
?>
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
.. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. ..
Bertrand Estellon (AMU) Dveloppement Web 2 April 1, 2014 175 / 436 Bertrand Estellon (AMU) Dveloppement Web 2 April 1, 2014 176 / 436
PHP Base de donnes Mapping objet-relationnel (ORM)

Redbean One-to-many

Le chargement de lintgralit du sondage est automatique :


<?
$surveys = R::find('survey', 'owner = ?', array($_SESSION['id']));

foreach ($surveys as &$survey) {


$total = 0;
foreach ($survey->ownResponse as $r)
$total += $r->count;

if ($total===0) {
foreach ($survey->ownResponse as &$r)
$r->percentage = 0;
} else {
foreach ($survey->ownResponse as &$r)
$r->percentage = (100*$r->count)/$total;
}
}
?>

. . . . . . . . . . . . . . . . . . . .
.. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. ..
Bertrand Estellon (AMU) Dveloppement Web 2 April 1, 2014 177 / 436