• Share
  • Email
  • Embed
  • Like
  • Save
  • Private Content
Présentation de DBAL en PHP
 

Présentation de DBAL en PHP

on

  • 2,914 views

Toute application Web dite dynamique nécessite une base de données ainsi que des outils qui permettront de manipuler ces données....

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).

Statistics

Views

Total Views
2,914
Views on SlideShare
2,914
Embed Views
0

Actions

Likes
2
Downloads
20
Comments
0

0 Embeds 0

No embeds

Accessibility

Categories

Upload Details

Uploaded via as Adobe PDF

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment

    Présentation de DBAL en PHP Présentation de DBAL en PHP Presentation Transcript

    • { Accès aux bases de données relationnelles et ORM en PHP
    • { Accès aux bases de données relationnelles et ORM en PHP 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 dabstraction de base de données) ou les ORM (Object Relational Mapping ou mapping objet- relationnel). 30/03/2011 Mickaël Perraud 2
    • { Accès aux bases de données relationnelles et ORM en PHP 3 interventions : Présentation de différents DBAL Présentation de 2 ORM : Propel Doctrine2 30/03/2011 Mickaël Perraud 3
    • { 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 30/03/2011 Mickaël Perraud 4
    • { Retournons en arrière On 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]; } 30/03/2011 Mickaël Perraud 5
    • { Retournons en arrière Puis 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()); } 30/03/2011 Mickaël Perraud 6
    • { Retournons en arrière Puis 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: //... 30/03/2011 Mickaël Perraud 7
    • { PDO PDO = PHP Data Object Ecrit en C Introduit en PHP 5.0 en 2004 Activé par défaut avec PHP 5.1 Fournit une interface dabstraction à laccès aux données Plus sécurisé (si bien utilisé) 30/03/2011 Mickaël Perraud 8
    • { 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 ) */ 30/03/2011 Mickaël Perraud 9
    • { PDO : reprenons notre exemple La 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 30/03/2011 Mickaël Perraud 10
    • { 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 30/03/2011 Mickaël Perraud 11
    • { PDO : lecture des résultats Il existe plusieurs manières de récupérer les résultats via PDO : $resultat = $stmt->fetchAll(PDO::FETCH_...); // Toutes les lignes //ou $resultat = $stmt->fetch(PDO::FETCH_...); // Ligne par ligne Et plusieurs mode de récupération (PDO::FETCH_*) : PDO::FETCH_ASSOC : Array ( [nom] => Perraud [prenom] => Mickael ) 30/03/2011 Mickaël Perraud 12
    • { PDO : lecture des résultats Et 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" } 30/03/2011 Mickaël Perraud 13
    • { 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 PDO 30/03/2011 Mickaël Perraud 14
    • { PDO::FETCH_CLASS Notre classe : class Utilisateur { private $_nom; private $_prenom; public function __set($attribut, $valeur) { $this->{"set".ucfirst($attribut)} = $valeur; } public function setNom($nom) { $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; } } 30/03/2011 Mickaël Perraud 15
    • { PDO::FETCH_CLASS Interrogeons 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 } 30/03/2011 Mickaël Perraud 16
    • { Ce que PDO ne fait pas Ne fournit pas une abstraction de base de données : il ne réécrit pas le SQL Il némule pas des fonctionnalités manquantes 30/03/2011 Mickaël Perraud 17
    • { Zend_Db Composant daccès aux bases de données de Zend Framework Contient 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 30/03/2011 Mickaël Perraud 18
    • { Zend_Db_Adapter Surcharge PDO et certaines extensions (MySQLi, Oci8, Db2, Sqlsrv) en fournissant une interface commune Instanciation via la fabrique de Zend_Db : $db = Zend_Db::factory(Pdo_Mysql, array(host => localhost, username => mysql_user, password => mysql_password, dbname => mysql_database)); 30/03/2011 Mickaël Perraud 19
    • { Zend_Db_Adapter Exé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)); 30/03/2011 Mickaël Perraud 20
    • { Zend_Db : lecture des résultats Outre fetchAll() ou fetch() de PDO (renommé en fetchRow()), on dispose de : fetchAssoc() fetchCol() fetchOne() fetchPairs() 30/03/2011 Mickaël Perraud 21
    • { Zend_Db : autres fonctions Gestion du schéma : listTables() describeTable() Interface générique de gestion des transactions (beginTransaction(), commit(), rollback()) Abstraction de la clause limit() 30/03/2011 Mickaël Perraud 22
    • { Zend_Db_Select Abstraction 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); 30/03/2011 Mickaël Perraud 23
    • { DoctrineDBAL Partie 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 30/03/2011 Mickaël Perraud 24
    • { DoctrineDBAL Connexion : $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 30/03/2011 Mickaël Perraud 25
    • { DoctrineDBAL : transation Transaction 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; } 30/03/2011 Mickaël Perraud 26
    • { DoctrineDBAL : schéma manager listDatabases() listSequences() listTables() listTableColumns() listTableDetails() listTableForeignKeys() listTableIndexes() listViews() createSchema() 30/03/2011 Mickaël Perraud 27
    • { DoctrineDBAL : schéma génération Cré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); 30/03/2011 Mickaël Perraud 28
    • { Ceux quil ne faut pas oublier ADOdb : 5.11 (PHP 5) PEAR::MDB2 : 2.5.0 en beta (PHP 5.3+) 30/03/2011 Mickaël Perraud 29
    • { 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+Requirements 30/03/2011 Mickaël Perraud 30