IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

PHP & Base de données Discussion :

Comprendre PDO [Tutoriel]


Sujet :

PHP & Base de données

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre confirmé
    Avatar de FMaz
    Inscrit en
    Mars 2005
    Messages
    643
    Détails du profil
    Informations forums :
    Inscription : Mars 2005
    Messages : 643
    Points : 640
    Points
    640
    Par défaut Comprendre PDO
    Bonjour à tous.

    Je viens de compléter un article portant sur ... PDO !
    Bien qu'il existe plusieurs articles du genre, je trouvais que la plupart expliquaient d'avantage comment utiliser PDO, mais rarement le pourquoi des choses. Ainsi, j'ai essayé de créer un article qui va au fond des choses en me remémorant tout ce que j'ai pus trouver complexe à saisir par moi-même au début.

    J'ai aussi tenté de cibler les principales incompréhensions que j'ai constaté sur le forum, et d'étayer des réponses les plus simples possible. Il s'agit donc d'un article de niveau débutant/intermédiaire.


    Pré-requis à la lecture:
    - Une base en PHP
    - Une base avec les fonctions mysql_ ou mysqli_
    - Un peu de temps

    Voici donc l'article en question:
    http://fmaz.developpez.com/tutoriels...omprendre-pdo/


    Vos commentaires seront les bienvenu !

  2. #2
    Modérateur
    Avatar de sabotage
    Homme Profil pro
    Inscrit en
    Juillet 2005
    Messages
    29 208
    Détails du profil
    Informations personnelles :
    Sexe : Homme

    Informations forums :
    Inscription : Juillet 2005
    Messages : 29 208
    Points : 44 155
    Points
    44 155
    Par défaut
    Une petite coquille : "l'extension MySQL a fait son temps. "

    Sinon ce genre d'articles est nécessaire car on voit bien sur le forum que mysql_ qui est le pire choix des trois reste largement utilisé.
    N'oubliez pas de consulter les FAQ PHP et les cours et tutoriels PHP

  3. #3
    Membre confirmé
    Avatar de FMaz
    Inscrit en
    Mars 2005
    Messages
    643
    Détails du profil
    Informations forums :
    Inscription : Mars 2005
    Messages : 643
    Points : 640
    Points
    640
    Par défaut
    Merci pour la coquille, c'est déjà corrigé

    Et ouais, c'est aussi ce que je me disais... En fait j'ai constaté que beaucoup de gens ne comprennent même pas ce qu'est une requête préparée, et qu'ils pensent que c'est une particularité de PDO...

    Et que d'autre pense que les requêtes préparés sont "l'unique" facon de faire une requête avec PDO: et que c'est beaucoup plus long qu'un mysql_query().

    Alors voilà, je voulais abattre ces quelques préjugés trop souvent mal expliqués.

  4. #4
    Expert confirmé
    Avatar de Doksuri
    Profil pro
    Développeur Web
    Inscrit en
    Juin 2006
    Messages
    2 457
    Détails du profil
    Informations personnelles :
    Âge : 54
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Juin 2006
    Messages : 2 457
    Points : 4 613
    Points
    4 613
    Par défaut
    bon petit article..simple et clair
    moi qui me mettais doucement a PDO... je vais abandonner les autres maintenant xD

    La forme des pyramides prouve que l'Homme a toujours tendance a en faire de moins en moins.

    Venez discuter sur le Chat de Développez !

  5. #5
    Membre éclairé

    Profil pro
    Inscrit en
    Juin 2004
    Messages
    772
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations forums :
    Inscription : Juin 2004
    Messages : 772
    Points : 872
    Points
    872
    Par défaut
    Bonjour,

    J'utilise PDO depuis longtemps et je trouve votre article bien rédigé, en expliquant bien ce qu'est et ce que n'est pas PDO...

    J'ai une question à propos :

    Pour des insertions massives en base, j'utilise le plus souvent les requêtes préparées sans les fonctions "bind" mais en passant directement un tableau de valeurs à la requête préparée :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    $prep = $db->prepare('INSERT INTO table (champ1, champ2, ..., champN) VALUES (:champ1, :champ2, ..., :champN);');
     
    $values = array(':champ1' => $value1, ':champ2' => $value2, ..., ':champN' => $valueN);
     
    $prep->execute->($values);
    Je me suis auparavant assurer du bon type des valeurs passées en paramètre. Mais je me demande si cette utilisation protège des injections SQL ?
    • Mon blog PHP : http://blog.alterphp.com
    • "Peace cannot be kept by force, it can only be achieved by Understanding" -- Albert Einstein

  6. #6
    Membre expert Avatar de RunCodePhp
    Profil pro
    Inscrit en
    Janvier 2010
    Messages
    2 962
    Détails du profil
    Informations personnelles :
    Localisation : Réunion

    Informations forums :
    Inscription : Janvier 2010
    Messages : 2 962
    Points : 3 947
    Points
    3 947
    Par défaut
    Salut

    Je lis actuellement avec beaucoup d'attention cet article.
    Excellent travail, faut le dire.

    J'en ai donc même terminé que je me suis empressé d'essayer cette ligne :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    $arrExtraParam= array(PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES utf8");
    Et là j'obtiens une erreur comme quoi la constante de classe MYSQL_ATTR_INIT_COMMAND n'existe pas.

    J'ai beau éplucher toutes les constantes PDO au niveau de la Doc, je ne la vois pas effectivement, et rien permettant de la remplacer.
    Je vois quand même celle ci : MYSQLI_INIT_COMMAND, donc pour MySQLi.
    Malgré tout, ce n'est pas une constante de classe de PDO.

    As tu eu cette erreur ?
    Personnellement je n'est pas d'idée du comment exploiter cette technique, actuellement j'effectue un PDO::exec('SET NAMES utf8').
    Win XP | WampServer 2.2d | Apache 2.2.21 | Php 5.3.10 | MySQL 5.5.20
    Si debugger, c'est supprimer des bugs, alors programmer ne peut être que les ajouter [Edsger Dijkstra]

  7. #7
    Membre confirmé
    Avatar de FMaz
    Inscrit en
    Mars 2005
    Messages
    643
    Détails du profil
    Informations forums :
    Inscription : Mars 2005
    Messages : 643
    Points : 640
    Points
    640
    Par défaut
    J'en ai donc même terminé que je me suis empressé d'essayer cette ligne :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    $arrExtraParam= array(PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES 
    utf8");
    Et là j'obtiens une erreur comme quoi la constante de classe MYSQL_ATTR_INIT_COMMAND n'existe pas.
    Bon alors oui la constante existe bien, voir: http://php.net/manual/fr/ref.pdo-mysql.php

    Note au passage concernant le fait que PHP exige des valeur entière: comme valeur, on peut mettre "SET NAMES utf8" ou l'entier 1002, ca reviend au même.

    Sinon tu peux simplement faire ceci:
    $db->query("SET NAMES 'utf8'");

    Edit: Sinon je recherche un peu, je crois avoir lu qu'il y avait un bug avec PHP 5.3 quelque part.
    Edit2: Ah voilà le bug en question: http://bugs.php.net/bug.php?id=47224 . En bref: c'est un bug dans php 5.3.0, et c'est corrigé dans la version 5.3.1.


    ---------------

    Pour des insertions massives en base, j'utilise le plus souvent les requêtes préparées sans les fonctions "bind" mais en passant directement un tableau de valeurs à la requête préparée :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    $prep = $db->prepare('INSERT INTO table (champ1, champ2, ..., champN) VALUES (:champ1, :champ2, ..., :champN);');
     
    $values = array(':champ1' => $value1, ':champ2' => $value2, ..., ':champN' => $valueN);
     
    $prep->execute->($values);
    Hum, je suis un peu hésitant. La pratique est tout à fait légitime, et il n'y a rien de mal à ne pas utiliser les méthodes de binding. Cependant, pour être honnête, je ne sais pas trop.

    Mais si tu ne mentionne rien, je crois (à valider) que par défaut la protection devrait être de type STRING pour toutes tes valeurs... (Tu pourrais essayer de reproduire le faux-bug du limit pour voir si c'est bien le cas)

    De plus, j'aimerais faire une mise en garde que l'utilisation des requêtes préparée n'est pas une protection absolue contre les injections. Vous devez tout de même valider vos entrés. (Donc si tu les a bien validée comme tu le dis, il ne devrait pas y avoir de problème).

  8. #8
    Expert éminent sénior

    Profil pro
    Inscrit en
    Septembre 2010
    Messages
    7 920
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2010
    Messages : 7 920
    Points : 10 726
    Points
    10 726
    Par défaut
    le bind ca sert surtout avec FETCH_BOUND.

  9. #9
    Membre expert Avatar de RunCodePhp
    Profil pro
    Inscrit en
    Janvier 2010
    Messages
    2 962
    Détails du profil
    Informations personnelles :
    Localisation : Réunion

    Informations forums :
    Inscription : Janvier 2010
    Messages : 2 962
    Points : 3 947
    Points
    3 947
    Par défaut
    Note au passage concernant le fait que PHP exige des valeur entière: comme valeur, on peut mettre "SET NAMES utf8" ou l'entier 1002, ca reviend au même.
    Oui, je m'en suis douté que cette constante retournerait un entier, mais vu quelle n'existe pas de mon coté (bug, surement), je ne voyait pas quelle valeur.

    J'ai remplacé comme ceci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    $arrExtraParam = array(1002 => 'SET NAMES utf8');
    Il n'y a certes plus d'erreur, mais je ne suis pas en UTF-8 pour autant.

    Bon, si tu as une idée, tant mieux, sinon je chercherais un peu plus longuement un autre jour.
    Pour le moment ce n'est franchement pas important, c'était plus par curiosité.

    Merci et excellent article encore une fois.
    Win XP | WampServer 2.2d | Apache 2.2.21 | Php 5.3.10 | MySQL 5.5.20
    Si debugger, c'est supprimer des bugs, alors programmer ne peut être que les ajouter [Edsger Dijkstra]

  10. #10
    Membre habitué
    Inscrit en
    Avril 2003
    Messages
    397
    Détails du profil
    Informations forums :
    Inscription : Avril 2003
    Messages : 397
    Points : 133
    Points
    133
    Par défaut
    Citation Envoyé par FMaz Voir le message
    De plus, j'aimerais faire une mise en garde que l'utilisation des requêtes préparée n'est pas une protection absolue contre les injections. Vous devez tout de même valider vos entrés. (Donc si tu les a bien validée comme tu le dis, il ne devrait pas y avoir de problème).
    Que faut-il faire alors pour s'assurer que la requête est protégée ?

  11. #11
    Membre du Club
    Homme Profil pro
    Ingénieur qualité méthodes
    Inscrit en
    Avril 2011
    Messages
    48
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : Ingénieur qualité méthodes
    Secteur : Transports

    Informations forums :
    Inscription : Avril 2011
    Messages : 48
    Points : 61
    Points
    61
    Par défaut coquille
    Bonjour,

    Il me semble avoir vu une petite faute dans l'instanciation de la connexion.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    $pdo = new PDO($connStr, 'Utilisateur', 'Mot de passe', $arrExtraParam);
    au lieu de :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    $pdo = new PDO($strConnection, 'Utilisateur', 'Mot de passe', $arrExtraParam);
    Sinon merci pour ce tuto,
    Bilal

  12. #12
    Membre éprouvé Avatar de redoran
    Homme Profil pro
    Développeur-Amateur
    Inscrit en
    Juin 2010
    Messages
    1 346
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Algérie

    Informations professionnelles :
    Activité : Développeur-Amateur
    Secteur : Santé

    Informations forums :
    Inscription : Juin 2010
    Messages : 1 346
    Points : 1 031
    Points
    1 031
    Par défaut
    L'article à été écris pour être une base d'apprentissage saine à PDO. J'ai donc essayé de casser certains "mythes". Par la suite, la lecture d'article plus poussée devrait être facilité.
    toute a fait d'accord , personnellement j'ai appris pas mal de choses encore bravo +++
    juste faut voir le format pdf qui est un peut mal imprimer (page 8) .

  13. #13
    Invité
    Invité(e)
    Par défaut
    Bonjour,
    Je découvre bien tardivement ton TOPO sur PDO !
    Un vrais bijoux, et pour cela mille bravos

    Je sais qu'il faut garder la "légéretée" a ton sujet, il n'empéche que
    le mécanisme du PREPARE qui reste un pilier de PDO
    (pas obligatoir comme tu l'a souligné) mériterait quelques précisions.

    A ce sujet je te soumet une analyse dont tu fera le trie si bon te semble
    pour l'incorporer si tu juges que cela n'alourdirait pas ton sujet.

    ____________________________________
    Préparé ou pas, avec ou sans bindparam, au final chaque exec envoie en une seule fois la requête et les vraies variables au gestionnaire de base de données (par exemple MySql) a la différence du PREPARE SQL !

    Dans un PREPARE (SQL par exemple) le gestionnaire reçoit et analyse la requête et attend tout envoi de données sur le pointeur de l'instruction préparée.

    Voilà pour le prépare ...
    ______________________________________

    Concernant "protection" "injection" et "échappement"

    l' injection doit être évitée par un contrôle (de notre choix)

    Pour le reste "protection" "échappement"

    Juste un petit historique que vous connaissez bien sur:

    Au début nous faisions avant un INSERT ou autre ... le fameux addslashes()
    avec la douce contrainte de contrôler l'état d' activation de ou non des magic_quotes_gpc...

    le résultat .. plein d' antislashs et obligé a la relecture de faire un
    stripslashes()

    Maintenant, les versions modernes de SQL / PHP ont cette superbe fonction
    mysql_real_escape_string qui fait EXACTEMENT la même chose que PDO

    A savoir doubler les ' et inscrire les caractères spéciaux et accentués sur deux octets ! ce qui protége bien les données.

    Ainsi la relecture est directe sans instructions !!
    ____________________________________

    A++ et encore BRAVO !
    Christele

  14. #14
    Modérateur
    Avatar de sabotage
    Homme Profil pro
    Inscrit en
    Juillet 2005
    Messages
    29 208
    Détails du profil
    Informations personnelles :
    Sexe : Homme

    Informations forums :
    Inscription : Juillet 2005
    Messages : 29 208
    Points : 44 155
    Points
    44 155
    Par défaut
    Préparé ou pas, avec ou sans bindparam, au final chaque exec envoie en une seule fois la requête et les vraies variables au gestionnaire de base de données (par exemple MySql) a la différence du PREPARE SQL !
    Pour Mysql (je ne sais pas pour les autres drivers), la préparation est par défaut émulé par soucis de compatibilité avec mysql < 5.1 mais il est possible d'utiliser la préparation du serveur mysql en changeant le paramètre ATTR_EMULATE_PREPARES.

    Maintenant, les versions modernes de SQL / PHP ont cette superbe fonction
    mysql_real_escape_string qui fait EXACTEMENT la même chose que PDO
    pas vraiment moderne : cette fonction existe depuis 11 ans et est maintenant classé comme obsolète à ne plus utiliser.
    Quand au fait qu'elle ferrait la même chose que PDO je ne vois pas trop à quoi tu fais référence.
    A savoir doubler les ' et inscrire les caractères spéciaux et accentués sur deux octets ! ce qui protége bien les données.
    Les accents ne posent pas de problème dans les requêtes et ne sont pas modifiés par mysql_real_escape_string. Ca serait d'ailleurs bien gênant d'avoir des caractères multioctet dans un encodage simple octet non ?
    N'oubliez pas de consulter les FAQ PHP et les cours et tutoriels PHP

  15. #15
    Invité
    Invité(e)
    Par défaut
    Citation Envoyé par sabotage Voir le message
    Pour Mysql (je ne sais pas pour les autres drivers), la préparation est par défaut émulé par soucis de compatibilité avec mysql < 5.1 mais il est possible d'utiliser la préparation du serveur mysql en changeant le paramètre ATTR_EMULATE_PREPARES.
    Je n'ais pas contrôlé depuis longtemps, mais par défault j'étais "True" de base


    Citation Envoyé par sabotage Voir le message
    mysql_real_escape_string()
    pas vraiment moderne : cette fonction existe depuis 11 ans et est maintenant classé comme obsolète à ne plus utiliser.
    Quand au fait qu'elle ferrait la même chose que PDO je ne vois pas trop à quoi tu fais référence.
    Je fais référence justement a la protection des données tels que je l'ais écris
    plus bas.


    Citation Envoyé par sabotage Voir le message
    Les accents ne posent pas de problème dans les requêtes et ne sont pas modifiés par mysql_real_escape_string. Ca serait d'ailleurs bien gênant d'avoir des caractères multioctet dans un encodage simple octet non ?
    Oui tu as raison Sabotage, mais c'est ce que m'indique mon éditeur hexadécimal
    Dans un fichier non UTF8 j'ais bien cela ... mais tu me mets le doute,
    c'est peut-étre l'export en *.SQL qui provoque cela ???

    Bref tu m'as mis un gros doute sur tout cela, je vais appronfondir ces trois points

    A++ et merci
    Christele

Discussions similaires

  1. [PDO] Problème de requête préparée (à n'y rien comprendre?)
    Par waldo2188 dans le forum Bibliothèques et frameworks
    Réponses: 3
    Dernier message: 20/03/2007, 21h53
  2. [Concept][JavaBeans] Comprendre ?
    Par nicoo dans le forum Langage
    Réponses: 15
    Dernier message: 08/12/2004, 08h01
  3. [Procédure][java] A n'y rien comprendre
    Par Stessy dans le forum SQL
    Réponses: 2
    Dernier message: 18/03/2004, 15h05

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo