SlideShare une entreprise Scribd logo
1  sur  30
Télécharger pour lire hors ligne
{
     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

Contenu connexe

Tendances

Chapitre 2 classe et objet
Chapitre 2   classe et objetChapitre 2   classe et objet
Chapitre 2 classe et objetAmir Souissi
 
Programmation orientée objet : Object, classe et encapsulation
Programmation orientée objet : Object, classe et encapsulationProgrammation orientée objet : Object, classe et encapsulation
Programmation orientée objet : Object, classe et encapsulationECAM Brussels Engineering School
 
PHP #3 : tableaux & formulaires
PHP #3 : tableaux & formulairesPHP #3 : tableaux & formulaires
PHP #3 : tableaux & formulairesJean Michel
 
.php1 : les fondamentaux du PHP
.php1 : les fondamentaux du PHP.php1 : les fondamentaux du PHP
.php1 : les fondamentaux du PHPAbdoulaye Dieng
 
Quickie Incanter/Clojure à Devoxx France 2012
Quickie Incanter/Clojure à Devoxx France 2012Quickie Incanter/Clojure à Devoxx France 2012
Quickie Incanter/Clojure à Devoxx France 2012Claude Falguiere
 
Fmin103 0910 tpjdbc
Fmin103 0910 tpjdbcFmin103 0910 tpjdbc
Fmin103 0910 tpjdbcKarim Amane
 
Symfony2 - Un Framework PHP 5 Performant
Symfony2 - Un Framework PHP 5 PerformantSymfony2 - Un Framework PHP 5 Performant
Symfony2 - Un Framework PHP 5 PerformantHugo Hamon
 
Php 2 - Approfondissement MySQL, PDO et MVC
Php 2 - Approfondissement MySQL, PDO et MVCPhp 2 - Approfondissement MySQL, PDO et MVC
Php 2 - Approfondissement MySQL, PDO et MVCPierre Faure
 

Tendances (16)

Ch06
Ch06Ch06
Ch06
 
Marzouk collection-map
Marzouk collection-mapMarzouk collection-map
Marzouk collection-map
 
Gestion de formulaires en PHP
Gestion de formulaires en PHPGestion de formulaires en PHP
Gestion de formulaires en PHP
 
Ch03
Ch03Ch03
Ch03
 
Python avancé : Tuple et objet
Python avancé : Tuple et objetPython avancé : Tuple et objet
Python avancé : Tuple et objet
 
Syntaxe du langage PHP
Syntaxe du langage PHPSyntaxe du langage PHP
Syntaxe du langage PHP
 
Chapitre 2 classe et objet
Chapitre 2   classe et objetChapitre 2   classe et objet
Chapitre 2 classe et objet
 
Programmation orientée objet : Object, classe et encapsulation
Programmation orientée objet : Object, classe et encapsulationProgrammation orientée objet : Object, classe et encapsulation
Programmation orientée objet : Object, classe et encapsulation
 
Structure de données en PHP
Structure de données en PHPStructure de données en PHP
Structure de données en PHP
 
PHP #3 : tableaux & formulaires
PHP #3 : tableaux & formulairesPHP #3 : tableaux & formulaires
PHP #3 : tableaux & formulaires
 
.php1 : les fondamentaux du PHP
.php1 : les fondamentaux du PHP.php1 : les fondamentaux du PHP
.php1 : les fondamentaux du PHP
 
Quickie Incanter/Clojure à Devoxx France 2012
Quickie Incanter/Clojure à Devoxx France 2012Quickie Incanter/Clojure à Devoxx France 2012
Quickie Incanter/Clojure à Devoxx France 2012
 
Fmin103 0910 tpjdbc
Fmin103 0910 tpjdbcFmin103 0910 tpjdbc
Fmin103 0910 tpjdbc
 
Symfony2 - Un Framework PHP 5 Performant
Symfony2 - Un Framework PHP 5 PerformantSymfony2 - Un Framework PHP 5 Performant
Symfony2 - Un Framework PHP 5 Performant
 
Python avancé : Classe et objet
Python avancé : Classe et objetPython avancé : Classe et objet
Python avancé : Classe et objet
 
Php 2 - Approfondissement MySQL, PDO et MVC
Php 2 - Approfondissement MySQL, PDO et MVCPhp 2 - Approfondissement MySQL, PDO et MVC
Php 2 - Approfondissement MySQL, PDO et MVC
 

En vedette

Techniques d'accélération des pages web
Techniques d'accélération des pages webTechniques d'accélération des pages web
Techniques d'accélération des pages webJean-Pierre Vincent
 
Get Soaked - An In Depth Look At PHP Streams
Get Soaked - An In Depth Look At PHP StreamsGet Soaked - An In Depth Look At PHP Streams
Get Soaked - An In Depth Look At PHP StreamsDavey Shafik
 
Automation using-phing
Automation using-phingAutomation using-phing
Automation using-phingRajat Pandit
 
Electrify your code with PHP Generators
Electrify your code with PHP GeneratorsElectrify your code with PHP Generators
Electrify your code with PHP GeneratorsMark Baker
 
The quest for global design principles (SymfonyLive Berlin 2015)
The quest for global design principles (SymfonyLive Berlin 2015)The quest for global design principles (SymfonyLive Berlin 2015)
The quest for global design principles (SymfonyLive Berlin 2015)Matthias Noback
 
Top tips my_sql_performance
Top tips my_sql_performanceTop tips my_sql_performance
Top tips my_sql_performanceafup Paris
 
Understanding Craftsmanship SwanseaCon2015
Understanding Craftsmanship SwanseaCon2015Understanding Craftsmanship SwanseaCon2015
Understanding Craftsmanship SwanseaCon2015Marcello Duarte
 
Why elasticsearch rocks!
Why elasticsearch rocks!Why elasticsearch rocks!
Why elasticsearch rocks!tlrx
 
Writing infinite scalability web applications with PHP and PostgreSQL
Writing infinite scalability web applications with PHP and PostgreSQLWriting infinite scalability web applications with PHP and PostgreSQL
Writing infinite scalability web applications with PHP and PostgreSQLGabriele Bartolini
 
Si le tdd est mort alors pratiquons une autopsie mix-it 2015
Si le tdd est mort alors pratiquons une autopsie mix-it 2015Si le tdd est mort alors pratiquons une autopsie mix-it 2015
Si le tdd est mort alors pratiquons une autopsie mix-it 2015Bruno Boucard
 
L'ABC du BDD (Behavior Driven Development)
L'ABC du BDD (Behavior Driven Development)L'ABC du BDD (Behavior Driven Development)
L'ABC du BDD (Behavior Driven Development)Arnauld Loyer
 
Performance serveur et apache
Performance serveur et apachePerformance serveur et apache
Performance serveur et apacheafup Paris
 
TDD with PhpSpec - Lone Star PHP 2016
TDD with PhpSpec - Lone Star PHP 2016TDD with PhpSpec - Lone Star PHP 2016
TDD with PhpSpec - Lone Star PHP 2016CiaranMcNulty
 
The Wonderful World of Symfony Components
The Wonderful World of Symfony ComponentsThe Wonderful World of Symfony Components
The Wonderful World of Symfony ComponentsRyan Weaver
 

En vedette (20)

Elastic Searching With PHP
Elastic Searching With PHPElastic Searching With PHP
Elastic Searching With PHP
 
Diving deep into twig
Diving deep into twigDiving deep into twig
Diving deep into twig
 
Techniques d'accélération des pages web
Techniques d'accélération des pages webTechniques d'accélération des pages web
Techniques d'accélération des pages web
 
Get Soaked - An In Depth Look At PHP Streams
Get Soaked - An In Depth Look At PHP StreamsGet Soaked - An In Depth Look At PHP Streams
Get Soaked - An In Depth Look At PHP Streams
 
PHP5.5 is Here
PHP5.5 is HerePHP5.5 is Here
PHP5.5 is Here
 
Automation using-phing
Automation using-phingAutomation using-phing
Automation using-phing
 
Electrify your code with PHP Generators
Electrify your code with PHP GeneratorsElectrify your code with PHP Generators
Electrify your code with PHP Generators
 
The quest for global design principles (SymfonyLive Berlin 2015)
The quest for global design principles (SymfonyLive Berlin 2015)The quest for global design principles (SymfonyLive Berlin 2015)
The quest for global design principles (SymfonyLive Berlin 2015)
 
Mocking Demystified
Mocking DemystifiedMocking Demystified
Mocking Demystified
 
Top tips my_sql_performance
Top tips my_sql_performanceTop tips my_sql_performance
Top tips my_sql_performance
 
Understanding Craftsmanship SwanseaCon2015
Understanding Craftsmanship SwanseaCon2015Understanding Craftsmanship SwanseaCon2015
Understanding Craftsmanship SwanseaCon2015
 
Why elasticsearch rocks!
Why elasticsearch rocks!Why elasticsearch rocks!
Why elasticsearch rocks!
 
Writing infinite scalability web applications with PHP and PostgreSQL
Writing infinite scalability web applications with PHP and PostgreSQLWriting infinite scalability web applications with PHP and PostgreSQL
Writing infinite scalability web applications with PHP and PostgreSQL
 
Si le tdd est mort alors pratiquons une autopsie mix-it 2015
Si le tdd est mort alors pratiquons une autopsie mix-it 2015Si le tdd est mort alors pratiquons une autopsie mix-it 2015
Si le tdd est mort alors pratiquons une autopsie mix-it 2015
 
L'ABC du BDD (Behavior Driven Development)
L'ABC du BDD (Behavior Driven Development)L'ABC du BDD (Behavior Driven Development)
L'ABC du BDD (Behavior Driven Development)
 
Behat 3.0 meetup (March)
Behat 3.0 meetup (March)Behat 3.0 meetup (March)
Behat 3.0 meetup (March)
 
Performance serveur et apache
Performance serveur et apachePerformance serveur et apache
Performance serveur et apache
 
TDD with PhpSpec - Lone Star PHP 2016
TDD with PhpSpec - Lone Star PHP 2016TDD with PhpSpec - Lone Star PHP 2016
TDD with PhpSpec - Lone Star PHP 2016
 
Caching on the Edge
Caching on the EdgeCaching on the Edge
Caching on the Edge
 
The Wonderful World of Symfony Components
The Wonderful World of Symfony ComponentsThe Wonderful World of Symfony Components
The Wonderful World of Symfony Components
 

Similaire à Présentation de DBAL en PHP

Présentation de DBAL en PHP (Nantes)
Présentation de DBAL en PHP (Nantes)Présentation de DBAL en PHP (Nantes)
Présentation de DBAL en PHP (Nantes)Mickael Perraud
 
Open close principle, on a dit étendre, pas extends !
Open close principle, on a dit étendre, pas extends !Open close principle, on a dit étendre, pas extends !
Open close principle, on a dit étendre, pas extends !Engineor
 
PHP 5 pour les développeurs Java
PHP 5 pour les développeurs JavaPHP 5 pour les développeurs Java
PHP 5 pour les développeurs JavaMehdi EL KRARI
 
Meet up symfony 11 octobre 2016 - Les formulaire
Meet up symfony 11 octobre 2016 - Les formulaireMeet up symfony 11 octobre 2016 - Les formulaire
Meet up symfony 11 octobre 2016 - Les formulaireJulien Vinber
 
Développement Web- PHP (partie II).pdf
Développement Web- PHP (partie II).pdfDéveloppement Web- PHP (partie II).pdf
Développement Web- PHP (partie II).pdfYasushiTsubakik
 
Découpler votre code pour assurer la réutilisabilité et la maintenabilite ...
Découpler votre code pour assurer la réutilisabilité et la maintenabilite ...Découpler votre code pour assurer la réutilisabilité et la maintenabilite ...
Découpler votre code pour assurer la réutilisabilité et la maintenabilite ...Fabien Potencier
 
Play framework - Human Talks Grenoble - 12.02.2013
Play framework - Human Talks Grenoble - 12.02.2013Play framework - Human Talks Grenoble - 12.02.2013
Play framework - Human Talks Grenoble - 12.02.2013Xavier NOPRE
 
Quelle place pour le framework Rails dans le développement d'application web
Quelle place pour le framework Rails dans le développement d'application webQuelle place pour le framework Rails dans le développement d'application web
Quelle place pour le framework Rails dans le développement d'application web5pidou
 
Function oop - bonnes pratiques ms tech days
Function   oop - bonnes pratiques ms tech daysFunction   oop - bonnes pratiques ms tech days
Function oop - bonnes pratiques ms tech daysJean-Pierre Vincent
 
S2-02-PHP-objet.pptx
S2-02-PHP-objet.pptxS2-02-PHP-objet.pptx
S2-02-PHP-objet.pptxkohay75604
 
Php mysql cours
Php mysql coursPhp mysql cours
Php mysql courszan
 
Les principes de base de PHP
 Les principes de base de PHP  Les principes de base de PHP
Les principes de base de PHP EL JAOUARI Ahmed
 

Similaire à Présentation de DBAL en PHP (20)

Présentation de DBAL en PHP (Nantes)
Présentation de DBAL en PHP (Nantes)Présentation de DBAL en PHP (Nantes)
Présentation de DBAL en PHP (Nantes)
 
Client base de données en PHP5
Client base de données en PHP5Client base de données en PHP5
Client base de données en PHP5
 
Php Data Object
Php Data ObjectPhp Data Object
Php Data Object
 
Open close principle, on a dit étendre, pas extends !
Open close principle, on a dit étendre, pas extends !Open close principle, on a dit étendre, pas extends !
Open close principle, on a dit étendre, pas extends !
 
Php1
Php1Php1
Php1
 
PHP 5 pour les développeurs Java
PHP 5 pour les développeurs JavaPHP 5 pour les développeurs Java
PHP 5 pour les développeurs Java
 
Meet up symfony 11 octobre 2016 - Les formulaire
Meet up symfony 11 octobre 2016 - Les formulaireMeet up symfony 11 octobre 2016 - Les formulaire
Meet up symfony 11 octobre 2016 - Les formulaire
 
Cours PHP avancé
Cours PHP avancéCours PHP avancé
Cours PHP avancé
 
Développement Web- PHP (partie II).pdf
Développement Web- PHP (partie II).pdfDéveloppement Web- PHP (partie II).pdf
Développement Web- PHP (partie II).pdf
 
Playing With PHP 5.3
Playing With PHP 5.3Playing With PHP 5.3
Playing With PHP 5.3
 
De legacy à symfony
De legacy à symfonyDe legacy à symfony
De legacy à symfony
 
Découpler votre code pour assurer la réutilisabilité et la maintenabilite ...
Découpler votre code pour assurer la réutilisabilité et la maintenabilite ...Découpler votre code pour assurer la réutilisabilité et la maintenabilite ...
Découpler votre code pour assurer la réutilisabilité et la maintenabilite ...
 
Play framework - Human Talks Grenoble - 12.02.2013
Play framework - Human Talks Grenoble - 12.02.2013Play framework - Human Talks Grenoble - 12.02.2013
Play framework - Human Talks Grenoble - 12.02.2013
 
Quelle place pour le framework Rails dans le développement d'application web
Quelle place pour le framework Rails dans le développement d'application webQuelle place pour le framework Rails dans le développement d'application web
Quelle place pour le framework Rails dans le développement d'application web
 
Héritage et redéfinition de méthode
Héritage et redéfinition de méthodeHéritage et redéfinition de méthode
Héritage et redéfinition de méthode
 
Function oop - bonnes pratiques ms tech days
Function   oop - bonnes pratiques ms tech daysFunction   oop - bonnes pratiques ms tech days
Function oop - bonnes pratiques ms tech days
 
S2-02-PHP-objet.pptx
S2-02-PHP-objet.pptxS2-02-PHP-objet.pptx
S2-02-PHP-objet.pptx
 
Php mysql cours
Php mysql coursPhp mysql cours
Php mysql cours
 
Les principes de base de PHP
 Les principes de base de PHP  Les principes de base de PHP
Les principes de base de PHP
 
Php cours
Php coursPhp cours
Php cours
 

Plus de Mickael Perraud

Découvrez le noyau d'internationalisation du Zend Framework
Découvrez le noyau d'internationalisation du Zend FrameworkDécouvrez le noyau d'internationalisation du Zend Framework
Découvrez le noyau d'internationalisation du Zend FrameworkMickael Perraud
 
Introduction à Zend Framework 2
Introduction à Zend Framework 2Introduction à Zend Framework 2
Introduction à Zend Framework 2Mickael Perraud
 
Développement sécurisé d'applications avec Zend Framework
Développement sécurisé d'applications avec Zend FrameworkDéveloppement sécurisé d'applications avec Zend Framework
Développement sécurisé d'applications avec Zend FrameworkMickael Perraud
 
Tester les applications Zend Framework
Tester les applications Zend FrameworkTester les applications Zend Framework
Tester les applications Zend FrameworkMickael Perraud
 
Tirer parti des décorateurs de Zend_Form
Tirer parti des décorateurs de Zend_FormTirer parti des décorateurs de Zend_Form
Tirer parti des décorateurs de Zend_FormMickael Perraud
 
Quoi de neuf dans Zend Framework 1.10 ?
Quoi de neuf dans Zend Framework 1.10 ?Quoi de neuf dans Zend Framework 1.10 ?
Quoi de neuf dans Zend Framework 1.10 ?Mickael Perraud
 

Plus de Mickael Perraud (7)

Découvrez le noyau d'internationalisation du Zend Framework
Découvrez le noyau d'internationalisation du Zend FrameworkDécouvrez le noyau d'internationalisation du Zend Framework
Découvrez le noyau d'internationalisation du Zend Framework
 
Introduction à Zend Framework 2
Introduction à Zend Framework 2Introduction à Zend Framework 2
Introduction à Zend Framework 2
 
Zf2 ce-qui-va-changer
Zf2 ce-qui-va-changerZf2 ce-qui-va-changer
Zf2 ce-qui-va-changer
 
Développement sécurisé d'applications avec Zend Framework
Développement sécurisé d'applications avec Zend FrameworkDéveloppement sécurisé d'applications avec Zend Framework
Développement sécurisé d'applications avec Zend Framework
 
Tester les applications Zend Framework
Tester les applications Zend FrameworkTester les applications Zend Framework
Tester les applications Zend Framework
 
Tirer parti des décorateurs de Zend_Form
Tirer parti des décorateurs de Zend_FormTirer parti des décorateurs de Zend_Form
Tirer parti des décorateurs de Zend_Form
 
Quoi de neuf dans Zend Framework 1.10 ?
Quoi de neuf dans Zend Framework 1.10 ?Quoi de neuf dans Zend Framework 1.10 ?
Quoi de neuf dans Zend Framework 1.10 ?
 

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