Blog technique sur mes expériences de développeur.
7 août 2022
Comme je le disais, c’est le chapitre le plus compliqué de cette partie du tutoriel.
Bien que je vais tenter d’expliquer le mieux possible de quoi il s’agit, il est indispensable que vous ayez compris le reste de ce tutoriel !
Accrochez - vous, la fin du tutoriel est proche ! ;)
Ce cours était originalement publié sur la plateforme OpenClassrooms. La plateforme OpenClassrooms ayant supprimée ce tutoriel en 2020 et le tutoriel étant sous licence CC BY-SA 4.0, je vous propose de le (re)découvrir ici.
Qu’est-ce qu’un placeholder ?
Derrière ce mot barbare se cache en réalité la notion de requêtes “préparées”.
Quand les utiliser ?
Les placeholders s’utilisent généralement dans 2 cas.
Ce système de requête étant beaucoup plus rapide pour votre base de données, les placeholders seront privilégiés pour des requêtes exécutées plusieurs fois au cours de votre programme.
Ce système est également privilégié lorsque vos requêtes sont exécutées en fonction de variables. En effet, ce système permet alors de sécuriser vos requêtes, et notamment de protéger efficacement vos programmes contre les injections SQL.
Considérons par exemple les 2 requêtes suivantes :
INSERT INTO MARQUE (nomMarque) VALUES ('Volvo');
INSERT INTO MARQUE (nomMarque) VALUES ('Skoda');
Ces 2 requêtes permettent d’ajouter dans la table MARQUE
les marques Volvo et Skoda.
Avec vos connaissances actuelles, pour exécuter ces 2 requêtes, vous faites :
my $requete1 = 'INSERT INTO MARQUE (nomMarque) VALUES (\'Volvo\')';
my $prep = $dbd->do($requete1)
or die 'Impossible d\'exécuter la requête : '.$dbd->errstr;
my $requete2 = 'INSERT INTO MARQUE (nomMarque) VALUES (\'Skoda\')';
$prep = $dbd->do($requete2)
or die 'Impossible d\'exécuter la requête : '.$dbd->errstr;
Nous allons voir ensemble comment optimiser cette action via la mise en place d’un placeholder.
La mise en place d’un placeholder se découpe en 3 parties :
C’est la première étape. Même si vous ne faites pas encore le parallèle, sachez que vous savez déjà préparer une requête. En effet, c’est ce que vous faites à chaque fois lors de vos requêtes de sélection, grâce à la fonction prepare
du descripteur de base.
Pour utiliser un placeholder, vous devez donc préparer la requête. Contrairement aux requêtes de sélection, pour mettre en place un placeholder, la requête doit être écrite sans sa partie variable.
Je sais que ça peut paraître abstrait dit comme ça… En fait, la partie variable de la requête est remplacée par un marqueur. Ce marqueur est un point d’interrogation.
Voyons tout de suite ce que ça donne :
my $requete = 'INSERT INTO MARQUE (nomMarque) VALUES (?)';
my $prep = $dbd->prepare($requete)
or die 'Impossible de préparer la requête : '.$dbd->errstr;
À cette étape, la requête est prête à être exécutée. C’est d’ailleurs ce que nous allons faire, en appelant la fonction execute
que vous utilisez déjà pour vos requêtes de sélection.
Mais vous vous doutez bien qu’il y a une petite nouveauté !
Afin de reconstituer la partie variable de votre requête, il faut transmettre à la fonction execute
la liste de vos paramètres.
Ainsi, pour ajouter la marque “Volvo”, on fera :
$prep->execute('Volvo');
Il suffit de réitérer cette dernière ligne avec un autre argument pour exécuter l’autre requête d’insertion !
L’exploitation des résultats, quant à elle, ne change pas par rapport à ce que nous avons vu précédemment.
Afin de résumer ce que nous avons vu jusqu’ici sur les placeholders, voici le code source complet pour les 2 requêtes d’insertion précédentes.
#!/usr/bin/perl
use strict;
use DBI;
my $base = 'Zvoitures';
my $hote = '127.0.0.1';
my $login = 'root';
my $mdp = '';
my $dbd = DBI->connect("dbi:mysql:dbname=$base;host=$hote;",$login, $mdp)
or die 'Connexion impossible à la base de données : '.DBI::errstr;
my $requete = 'INSERT INTO MARQUE (nomMarque) VALUES (?)';
my $prep = $dbd->prepare($requete)
or die 'Impossible de préparer la requête : '.$dbd->errstr;
$prep->execute('Volvo');
$prep->execute('Skoda');
$prep->finish;
$dbd->disconnect;
Il est possible de réaliser les requêtes grâce à la concaténation, mais c’est TRÈS fortement déconseillé !
À la place, il est préférable d’utiliser les placeholders.
Par exemple, essayons de réaliser un script qui affiche l’identifiant dans la base de données d’un vendeur, dont le nom et le prénom sont renseignés par l’utilisateur.
#!/usr/bin/perl
use strict;
use DBI;
my $base = 'Zvoitures';
my $hote = '127.0.0.1';
my $login = 'root';
my $mdp = '';
print 'Saisir le prénom du vendeur : ';
my $prenom = <STDIN>;
chop($prenom);
print 'Saisir le nom du vendeur : ';
my $nom = <STDIN>;
chop($nom);
my $dbd = DBI->connect("dbi:mysql:dbname=$base;host=$hote;",$login, $mdp)
or die 'Connexion impossible à la base de données : '.DBI::errstr;
my $requete = 'SELECT numVendeur FROM VENDEUR WHERE nomVendeur = ? AND prenomVendeur = ?';
my $prep = $dbd->prepare($requete)
or die 'Impossible de préparer la requête : '.$dbd->errstr;
$prep->execute($nom, $prenom)
or die 'Impossible d\'exécuter la requête : '.$prep->errstr;
my ($num) = $prep->fetchrow_array;
$prep->finish;
print 'Le numéro du vendeur dans la base de données est : '.$num;
$dbd->disconnect;
En exécutant le script, vous devriez alors avoir l’affichage suivant :
> perl script_vendeur.pl
Saisir le prénom du vendeur : Batte
Saisir le nom du vendeur : MANE
Le numéro du vendeur dans la base de données est : 2
Bien que ce type de requêtes soit sécurisé, il est fortement conseillé d’ajouter une vérification des données saisies par l’utilisateur à l’aide par exemple d’expressions rationnelles !
Voilà, la partie sur le module DBI est maintenant terminée. J’espère que cette partie du tutoriel vous aura servi et surtout plu ! ;)