Cours PHP : Bases de données
PHP
Bertrand Estellon
Aix-Marseille Université
13 mars 2012
13 mars 2012 1 / 214
SQLite et PDO
SQLite et PDO
SQLite écrit les données relatives à la base dans un unique fichier sur le disque dur du serveur. La commande sqlite3 permet d’ouvrir la base et effectuer des requêtes SQL (pratique pour débugger).
PDO (PHP Data Objects) est une interface pour accéder à une base de données depuis PHP. Elle gère la connexion, l’envoie des requêtes, la déconnexion à la base de données. Elle permet de changer plus facilement de moteur de bases de données (Par exemple, SQLite ? MySQL).
Ouverture de la base :
<? try {
$bd = new PDO( ”s q l i t e : database . s q l i t e ”) ;
} catch ( PDOException $e ) { die ( ’ Erreur : ’ . $e?>getMessage ( ) ) ;
}
?>
Une fois l’instance de PDO construite, vous effectuez des requêtes avec :
I $bd->exec($requete) : pour modifier la base de données
I $bd->query($requete) : pour extraire des données de la base
Exemples :
$bd?>exec ( ”CREATE TABLE users ( ”.
” nickname char (20) , ”.
” password char (50) ”.
”) ; ”) ;
$res =$bd?>exec ( ’UPDATE users SET password=”’ .
md5( $password ) . ’ ” WHERE nickname=”’ . $nickname . ’ ”; ’ ) ;
echo ”nombre de l i g n e s modifiees = $res ”;
$res = $bd?>query ( ”s e l e c t nickname from users ; ”) ;
Injections SQL
Le code suivant :
$nickname = ’ aa ”; DELETE FROM users ; ’ .
’SELECT ? FROM users WHERE nickname=”’ ;
$password = ”truc ”;
$res = $bd?>exec ( ’UPDATE users SET password=”’ . md5( $password ) . ’ ” WHERE nickname=”’ . $nickname . ’ ”; ’ ) ;
exécute la requête SQL suivante :
UPDATE users SET password=” . . . . ” WHERE nickname=”aa ”;
DELETE FROM users ;
SELECT ? FROM users WHERE nickname=””; Protection contre les injections SQL :
$r = $bd?>prepare ( ’UPDATE users SET password = ? ’ .
’WHERE nickname = ? ’ ) ;
$r?>execute ( array (md5( $password ) , $nickname ) ) ;
Pour faire une requête SQL :
$res = $bd?>query ( ”s e l e c t ? from sondages ”) ; var dump ( $res ) ;
affiche ’object(PDOStatement)#2 (1) {
[”queryString”]=> string(19) ”select * from sondages”}’ Pour connaˆ?tre le nombre de lignes : echo ”nombre de l i g n e s : ”. $res?>rowCount () . ”\n ”; Pour parcourir les lignes :
$res = $bd?>query ( ”s e l e c t ? from sondages ”) ; while ( $ l i g n e = $res?>fetch () ) {
echo $ l i g n e [ ’ createur ’ ] .
” pose l a question
$ l i g n e [ ’ question ’ ] . ”\n ”;
}
Pour mettre toutes les lignes dans un tableau :
$res = $bd?>query ( ”s e l e c t ? from sondages ”) ;
$ l i g n e s = $res?>f e t c h A l l ( ) ; foreach ( $ l i g n e s as $ l i g n e ) { echo $ l i g n e [ ’ createur ’ ] .
” pose l a question : ”.
$ l i g n e [ ’ question ’ ] . ”\n ”;
}
Voir aussi, dans la classe PDOStatement, les méthodes :
I bindColumn : attache une variable à une colonne
I errorInfo : information d’erreur
I fetchColumn : récupère la valeur dans une colonne donnée
I closeCursor : ferme le curseur
Voir aussi, dans la classe PDO, les méthodes :
I beginTransaction : démarre une transaction
I commit : valide une transaction
I rollback : annule une transaction
I errorInfo : Retourne les informations associées à l’erreur
I errorCode : Retourne le SQLSTATE associé avec la dernière opération
I prepare : Prépare une requête à l’exécution et retourne un objet
I quote : Protège une chaˆ?ne pour l’utiliser dans une requête SQL PDO
$ s t r i n g = ’ Chaine \ ’ p a r t i c u l i e r e ’ ; p r i n t ”nonechappee : $ s t r i n g \n ”;
p r i n t ”echappee : ” . $bd?>quote ( $ s t r i n g ) . ”\n ”;
Chaine non echappee : Chaine ’ particuliere
Chaine echappee : ’Chaine ”particuliere’
Base de données du projet
Les trois tables utilisées dans le projet :
users ( nickname char (20) , password char ( 5 0 ) ) ;
surveys ( id i n t e g e r primary key autoincrement , owner char (20) , question char (255));
responses ( id i n t e g e r primary key autoincrement ,
i d s u r v e y integer ,
t i t l e char (255) , count i n t e g e r ) ;
Exemple : sauvegarde d’un sondage
p u b l i c function saveSurvey(&$survey ) { i f ( $survey?>getId ()!== n u l l ) return f a l s e ;
$this ?>connection?>beginTransaction () ;
$r = $this ?>connection?>prepare ( ’INSERT INTO surveys ( owner ,’ .
’ question ) VALUES ( ? , ? ) ; ’ ) ;
i f ( $r===f a l s e ) {
$this ?>connection?>r o l l b a c k () ; return f a l s e ;
} i f ( $r?>execute ( array ( $survey?>getOwner () ,
$survey?>getQuestion ()))=== f a l s e ) {
$this ?>connection?>r o l l b a c k () ; return f a l s e ; }
$id = $this ?>connection?>l a s t I n s e r t I d () ;
$survey?>se t Id ( $id ) ; foreach ( $survey?>getResponses () as $response ) i f (! $this ?>saveResponse ( $response )) { $this ?>connection?>r o l l b a c k () ; return f a l s e ;
}
$this ?>connection?>commit () ; return true ;
}
La classe Database
| p r i v a t e | $connection ; | |||||
| p u b l i c | function | c o n s t r u c t () { . . . } | ||||
| p u b l i c | function | checkPassword ( $nickname , $password ) { | . . . | } | ||
| p u b l i c | function | addUser ( $nickname , $password ) { . . . } | ||||
| p u b l i c | function | updateUser ( $nickname , $password ) { . . . | } | |||
| p u b l i c | function | saveSurvey(&$survey ) { . . . } | ||||
| p u b l i c | function | loadSurveysByOwner ( $owner ) { . . . } | ||||
| p u b l i c | function | loadSurveysByKeyword ( $keyword ) { . . . } | ||||
| p u b l i c | function | vote ( $id ) { . . . } | ||||
| p r i v a t e | function | createDataBase () { . . . } | ||||
| p r i v a t e | function | checkNicknameValidity ( $nickname ) { . . . } | ||||
| p r i v a t e | function | checkPasswordValidity ( $password ) { . . . } | ||||
| p r i v a t e | function | checkNicknameAvailability ( $nickname ) { . . . | } | |||
| p r i v a t e | function | saveResponse(&$response ) { . . . } | ||||
| p r i v a t e | function | loadSurveys ( $arraySurveys ) { . . . } | ||||
| p r i v a t e | function | loadResponses(&$survey , $arrayResponses ) { | . . . | } | ||
c l a s s Database {
}
Persistance et mapping objet-relationnel (ORM)
Les besoins :
I Sauvegarde simple des objets en base de données :
$user = new User ( ) ;
$user?>nickname = ”bob ”;
$user?>password = md5( ”truc ”) ;
$user?>save ( ) ;
I Création automatique des tables;
I Chargement des objets;
I Gestion des relations entre les objets/enregistrements; I ...
Quelques solutions en PHP :
I Propel
I Doctrine
I Zend Framework
I Redbean I ...
