Présentation de DBAL en PHP (Nantes)

2,535 views
2,434 views

Published on

Toute application Web dite dynamique nécessite une base de données ainsi que des outils qui permettront de manipuler ces données.Dans la palette des outils à la disposition des développeurs PHP, on trouve entre autres les DBAL (DataBase Abstraction Layer ou couche d'abstraction de base de données) ou les ORM (Object Relational Mapping ou mapping objet-relationnel).

Published in: Technology
0 Comments
1 Like
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
2,535
On SlideShare
0
From Embeds
0
Number of Embeds
5
Actions
Shares
0
Downloads
22
Comments
0
Likes
1
Embeds 0
No embeds

No notes for slide

Présentation de DBAL en PHP (Nantes)

  1. 1. Accès aux bases de donnéesrelationnelles et ORM en PHP
  2. 2. Accès aux bases de données relationnelles et ORM en PHPToute application Web dite dynamique nécessite unebase de données ainsi que des outils qui permettront demanipuler ces données.Dans la palette des outils à la disposition desdéveloppeurs PHP, on trouve entre autres les DBAL(DataBase Abstraction Layer ou couche dabstraction debase de données) ou les ORM (Object RelationalMapping ou mapping objet-relationnel). 29 juin 2011 Mickaël Perraud 2
  3. 3. Accès aux bases de données relationnelles et ORM en PHP3 interventions : Présentation de différents DBAL Présentation de lORM Doctrine2 Présentation de Pomm 29 juin 2011 Mickaël Perraud 3
  4. 4. Accès aux bases de données relationnelles Contributeur ZF depuis 2007 (Zend_Db, Zend_Barcode) Responsable documentation française Donne des webinars sur ZF en partenariat avec Zend Travaille sur laide à la traduction et propose les versions déconnectées de la documentation PDF / CHM Vice-trésorier AFUP 2011 @mikaelkael / http://mikaelkael.fr 29 juin 2011 Mickaël Perraud 4
  5. 5. Retournons en arrièreOn a commencé par tout écrire en dur : $lien = mysql_connect(localhost, mysql_user, mysql_password); if (!$lien) { die(Impossible de se connecter : . mysql_error()); } $db = mysql_select_db(foo, $lien); if (!$db) { die (Impossible de sélectionner la base de données : . mysql_error()); } $requete = SELECT * FROM maTable WHERE id = . $_GET[id]; $resultat = mysql_query($requete); while($ligne = mysql_fetch_assoc($resultat)) { echo $ligne[id].: .$ligne[valeur]; } 29 juin 2011 Mickaël Perraud 5
  6. 6. Retournons en arrièrePuis on a ”amélioré” : //config.php define(DB_HOST, localhost); define(DB_USERNAME, mysql_user); define(DB_PASSWORD, mysql_password); define(DB_DATABASE, mysql_base); //db.php require_once config.php; $lien = mysql_connect(DB_HOST, DB_USERNAME, DB_PASSWORD); if (!$lien) { die(Impossible de se connecter : . mysql_error()); } $db = mysql_select_db(DB_DATABASE, $lien); if (!$db) { die (Impossible de sélectionner la base de données : . mysql_error()); } 29 juin 2011 Mickaël Perraud 6
  7. 7. Retournons en arrièrePuis les classes sont arrivées : class BDD { var $connexion; function BDD() { $this->connexion = $this->connecte(DB_TYPE); } function connecte($type = mysql) { switch($type) { case mysql: return mysql_connect(DB_HOST, DB_USERNAME, DB_PASSWORD); break; case oci8: //... 29 juin 2011 Mickaël Perraud 7
  8. 8. PDOPDO = PHP Data ObjectEcrit en CIntroduit en PHP 5.0 en 2004Activé par défaut avec PHP 5.1Fournit une interface dabstraction à laccès auxdonnéesPlus sécurisé (si bien utilisé) 29 juin 2011 Mickaël Perraud 8
  9. 9. PDO : quelles bases de données ?Demandez à phpinfo() :Demandez à PDO : print_r(PDO::getAvailableDrivers()); /* Array ( [0] => sqlite [1] => dblib [2] => mysql [3] => oci [4] => odbc [5] => pgsql [6] => sqlite2 ) */ 29 juin 2011 Mickaël Perraud 9
  10. 10. PDO : reprenons notre exempleLa connexion : try { $dbh = new PDO(mysql:host=localhost;dbname= . DB_DATABASE, DB_USER, DB_PASSWORD); echo Connected!; } catch (PDOException $e) { echo $e->getMessage(); }En changeant de driver : try { $dbh = new PDO(oci:dbname= . DB_DATABASE, DB_USER, DB_PASSWORD); echo Connected!; } catch (PDOException $e) { echo $e->getMessage(); }Ce qui va suivre est désormais indépendant du driver 29 juin 2011 Mickaël Perraud 10
  11. 11. PDO : requêtes préparées PDO peut être utilisée avec ou sans requêtes préparées Pour des raisons de sécurité, préférez les requêtes préparées :$stmt = $dbh->prepare(SELECT nom, prenom FROM utilisateurs WHERE id_utilisateur = :id);$stmt->bindParam(id, $_GET[id], PDO::PARAM_INT);$stmt->execute();$resultat = $stmt->fetchAll(); Lassignation peut être nommée (ci-dessus) ou numérique 29 juin 2011 Mickaël Perraud 11
  12. 12. PDO : lecture des résultatsIl existe plusieurs manières de récupérer les résultats viaPDO : $resultat = $stmt->fetchAll(PDO::FETCH_...); // Toutes les lignes //ou $resultat = $stmt->fetch(PDO::FETCH_...); // Ligne par ligneEt plusieurs mode de récupération (PDO::FETCH_*) : PDO::FETCH_ASSOC : Array ( [nom] => Perraud [prenom] => Mickael ) 29 juin 2011 Mickaël Perraud 12
  13. 13. PDO : lecture des résultatsEt plusieurs mode de récupération (PDO::FETCH_*) : PDO::FETCH_NUM : Array ( [0] => Perraud [1] => Mickael ) PDO::FETCH_BOTH (par défaut) : Array ( [nom] => Perraud [0] => Perraud [prenom] => Mickael [1] => Mickael ) PDO::FETCH_OBJ : object(stdClass)#1 (2) { ["nom"]=> string(7) "Perraud" ["prenom"]=> string(7) "Mickael" } 29 juin 2011 Mickaël Perraud 13
  14. 14. PDO : lecture des résultats Le meilleur pour la fin ? PDO::FETCH_CLASS Prend un résultat et le retourne sous la forme dune classe On peut instancier la classe directement par PDO29 juin 2011 Mickaël Perraud 14
  15. 15. PDO::FETCH_CLASS class Utilisateur { private $_nom; private $_prenom; public function __set($attribut, $valeur) { $this->{"set".ucfirst($attribut)} = $valeur; } public function setNom($nom) {Notre classe : $this->_nom = $nom; } public function getNom() class Utilisateur { { public $nom; return $this->_nom; public $prenom; } } public function setPrenom($prenom) { $this->_prenom = $prenom; } public function getPrenom() { return $this->_prenom; } public function __toString() { return $this->_prenom . . $this->_nom; } } 29 juin 2011 Mickaël Perraud 15
  16. 16. PDO::FETCH_CLASSInterrogeons la base : $stmt = $dbh->prepare(SELECT * FROM utilisateurs); $resultat = $stmt->fetchAll(PDO::FETCH_CLASS, Utilisateur); foreach($resultat as $class) { echo $class; // Affiche par exemple : Mickael Perraud } 29 juin 2011 Mickaël Perraud 16
  17. 17. Ce que PDO ne fait pasNe fournit pas une abstraction de base de données : il ne réécrit pas le SQL Il némule pas des fonctionnalités manquantes 29 juin 2011 Mickaël Perraud 17
  18. 18. Zend_DbComposant daccès aux bases de données de Zend FrameworkContient différents sous composants : Zend_Db_Adapter : abstraction de base de données Zend_Db_Select : abstraction de requête de type ”SELECT” Zend_Db_Table : ”Table Data Gateway” - http://martinfowler.com/eaaCatalog/tableDataGateway.html Zend_Db_Table_Row : ”Row Data Gateway” - http://martinfowler.com/eaaCatalog/rowDataGateway.html 29 juin 2011 Mickaël Perraud 18
  19. 19. Zend_Db_AdapterSurcharge PDO et certaines extensions (MySQLi, Oci8, Db2, Sqlsrv)en fournissant une interface communeInstanciation via la fabrique de Zend_Db : $db = Zend_Db::factory(Pdo_Mysql, array(host => localhost, username => mysql_user, password => mysql_password, dbname => mysql_database)); 29 juin 2011 Mickaël Perraud 19
  20. 20. Zend_Db_AdapterExécution de requêtes préparées : $stmt = $db->query(SELECT * FROM utilisateurs WHERE id_utilisateur = ?, array($_GET[id]));Abstraction DML (”INSERT”, ”UPDATE”, ”DELETE”) : $id = $db->insert(utilisateurs, array(nom => Doe, prenom => John)); $db->update(utilisateurs, array(nom => Doe, prenom => Jane), array(id_utilisateur = ? => 2)); $db->delete(utilisateurs, array(id_utilisateur = ? => 2)); 29 juin 2011 Mickaël Perraud 20
  21. 21. Zend_Db : lecture des résultatsOutre fetchAll() ou fetch() de PDO (renommé en fetchRow()),on dispose de : fetchAssoc() fetchCol() fetchOne() fetchPairs() 29 juin 2011 Mickaël Perraud 21
  22. 22. Zend_Db : autres fonctionsGestion du schéma : listTables() describeTable()Interface générique de gestion des transactions(beginTransaction(), commit(), rollback())Abstraction de la clause limit() 29 juin 2011 Mickaël Perraud 22
  23. 23. Zend_Db_SelectAbstraction DQL : permet de construire des requêtes de type”SELECT” en PHP // Construire cette requête : // SELECT produit_id, produit_nom, prix // FROM "produits" // WHERE (prix > 100.00) // AND (prix < 500.00) $prixminimum = 100; $prixmaximum = 500; $select = $db->select() ->from(produits, array(produit_id, produit_nom, prix)) ->where(prix > ?, $prixminimum) ->where(prix < ?, $prixmaximum); 29 juin 2011 Mickaël Perraud 23
  24. 24. DoctrineDBALPartie de Doctrine destinée à labstraction des bases de données :Plusieurs sous-composants : DoctrineDBALDriver : surcouche de PDO et quelques drivers (pas de SQL) DoctrineDBALPlatform : abstraction de la génération de requêtes et de fonctionnalités (SQL) DoctrineDBALSchema : abstraction de la gestion du schéma DoctrineDBALType : abstraction du typage avec mapping PHP 29 juin 2011 Mickaël Perraud 24
  25. 25. DoctrineDBALConnexion : $connexion = DriverManager::getConnection(array(dbname => mysql_database, user => mysql_user, password => mysql_password, host => localhost, driver => pdo_mysql));Exécution de requêtes préparées : $sql = "SELECT * FROM utilisateurs WHERE id = ? AND status = ?"; $stmt = $connexion->prepare($sql); $stmt->bindValue(1, $id); $stmt->bindValue(2, $status); $stmt->execute();On retrouve une API de récupération de données très similaire àce qui précède pour Zend_Db 29 juin 2011 Mickaël Perraud 25
  26. 26. DoctrineDBAL : transationTransaction imbriquées : // $connexion instanceof DoctrineDBALConnection $connexion->beginTransaction(); // 0 => 1, transaction "réelle" démarrée try { //... // nested transaction block, this might be in some other API/library code that is // unaware of the outer transaction. $connexion->beginTransaction(); // 1 => 2 try { //... $connexion->commit(); // 2 => 1 } catch (Exception $e) { $connexion->rollback(); // 2 => 1, transaction marquée pour annulation throw $e; } //... $connexion->commit(); // 1 => 0, transaction "réelle" confirmée } catch (Exception $e) { $connexion->rollback(); // 1 => 0, transaction "réelle" annulée throw $e; } 29 juin 2011 Mickaël Perraud 26
  27. 27. DoctrineDBAL : schéma manager listDatabases() listSequences() listTables() listTableColumns() listTableDetails() listTableForeignKeys() listTableIndexes() listViews() createSchema()29 juin 2011 Mickaël Perraud 27
  28. 28. DoctrineDBAL : schéma générationCréation table utilisateur : $schema = new DoctrineDBALSchemaSchema(); $maTable = $schema->createTable("utilisateurs"); $maTable->addColumn("id_utilisateur", "integer", array("unsigned" => true)); $maTable->addColumn("nom", "string", array("length" => 50)); $maTable->addColumn("prenom", "string", array("length" => 50)); $maTable->setPrimaryKey(array("id_utilisateur")); $schema->createSequence("utilisateurs_seq"); $myForeign = $schema->createTable("commentaires"); $myForeign->addColumn("id_commentaire", "integer"); $myForeign->addColumn("utilisateur_id", "integer"); $myForeign->addForeignKeyConstraint($myTable, array("utilisateur_id"), array("id_utilisateur"), array("onUpdate" => "CASCADE")); // Récupérer les requêtes pour générer le schéma $queries = $schema->toSql($myPlatform); // Récupérer les requêtes pour effacer le schéma $dropSchema = $schema->toDropSql($myPlatform); 29 juin 2011 Mickaël Perraud 28
  29. 29. Ceux quil ne faut pas oublier ADOdb : 5.11 (PHP 5) PEAR::MDB2 : 2.5.0 en beta (PHP 5.3+)29 juin 2011 Mickaël Perraud 29
  30. 30. ZendDb 2.0 ZendDbAdapter : ajout plugin (pre- post-connect), suppression du SQL pur ZendDbQuery : abstraction DML, DQL, ainsi que DDL (”alter”, ”create”, ”drop”) et DCL (”commit”, ”rollback”, ”savepoint”), supporte ANSI ainsi que les dialectes des SGBD ZendDbResultSet : modélisation des résultats ZendDbMetadata : gestion du schéma http://framework.zend.com/wiki/display/ZFDEV2/Zend+Db+2.0+Requirements29 juin 2011 Mickaël Perraud 30

×