{
     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
    d'abstraction 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 l'aide à 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 d'abstraction à l'accè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();



       L'assignation 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
    d'une 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 d'accè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 à l'abstraction 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 qu'il 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

Présentation de DBAL en PHP

  • 1.
    { Accès aux bases de données relationnelles et ORM en PHP
  • 2.
    { 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 d'abstraction de base de données) ou les ORM (Object Relational Mapping ou mapping objet- relationnel). 30/03/2011 Mickaël Perraud 2
  • 3.
    { 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
  • 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 l'aide à 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
  • 5.
    { 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
  • 6.
    { 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
  • 7.
    { 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
  • 8.
    { 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 d'abstraction à l'accès aux données Plus sécurisé (si bien utilisé) 30/03/2011 Mickaël Perraud 8
  • 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 ) */ 30/03/2011 Mickaël Perraud 9
  • 10.
    { 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
  • 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(); L'assignation peut être nommée (ci-dessus) ou numérique 30/03/2011 Mickaël Perraud 11
  • 12.
    { 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
  • 13.
    { 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
  • 14.
    { PDO : lecture des résultats Le meilleur pour la fin ? PDO::FETCH_CLASS Prend un résultat et le retourne sous la forme d'une classe On peut instancier la classe directement par PDO 30/03/2011 Mickaël Perraud 14
  • 15.
    { 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
  • 16.
    { 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
  • 17.
    { 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
  • 18.
    { Zend_Db Composant d'accè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
  • 19.
    { 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
  • 20.
    { 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
  • 21.
    { 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
  • 22.
    { 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
  • 23.
    { 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
  • 24.
    { DoctrineDBAL Partie de Doctrine destinée à l'abstraction 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
  • 25.
    { 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
  • 26.
    { 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
  • 27.
    { DoctrineDBAL : schéma manager listDatabases() listSequences() listTables() listTableColumns() listTableDetails() listTableForeignKeys() listTableIndexes() listViews() createSchema() 30/03/2011 Mickaël Perraud 27
  • 28.
    { 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
  • 29.
    { Ceux qu'il 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
  • 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+Requirements 30/03/2011 Mickaël Perraud 30