Vous pouvez me contacter via Facebook pour questions & suggestions :
Page Facebook relative à mon site
Dans ce chapitre je vais présenter les vues (view) c'est à dire les tables virtuelles
et les requêtes préparées qui sont très importantes en matière de sécurité.
Mais auparavant je veux vous montrer une astuce afin que le code SQL des requêtes multitables
ne soit pas pas trop lourd.
Pour les requêtes multitables et afin de simplifier la syntaxe il est conseillé d'utiliser des alias de champs mais surtout des alias de tables.
SELECT billets.id_billet as idb, id_commentaire, titre, contenu, date_format(date_billet,'%d-%m-%Y')AS date_billet, auteur, commentaire FROM billets INNER JOIN commentaires ON billets.id_billet = commentaires.id_billet ORDER BY billets.id_billet ;
La table "billets" aura pour alias "b" et la table "commentaires" aura pour alias "c".
On peut alors écrire :
SELECT b.id_billet, c.id_billet, id_commentaire, titre, contenu, date_format(date_billet,'%d-%m-%Y')AS date_billet, auteur, commentaire FROM billets b INNER JOIN commentaires c ON b.id_billet = c.id_billet ORDER BY b.id_billet ;
Volontairement j'affiche les deux champs de jointure : b.id_billet & c.id_billet.
Je ne peux que vous conseiller de tester vous même ce code à partir de PHPMYADM (en local ou chez votre hébergeur).
Une vue est une requête sélection (en général complexe) qui est mémorisée dans la base.
L'exécution de la vue produit une table virtuelle.
Je vais mémoriser la jointure interne entre les tables 'billets' & 'commentaires' sous forme d'une vue.
J'accéde à PHPMYADIM chez mon hébergeur, je sélectionne la base et je colle dans l'onglet "SQL" le code suivant :
CREATE VIEW inner_join AS SELECT b.id_billet, id_commentaire, titre, contenu, date_format(date_billet,'%d-%m-%Y')AS date_billet, auteur, commentaire FROM billets b INNER JOIN commentaires c ON b.id_billet = c.id_billet ORDER BY b.id_billet ;
Je reprends donc exactement le code de la jointure interne entre "billets" & "commentaires".
Mais afin que cette requête soit mémorisée dans la base sous forme d'une vue, je fais précéder
par "CREATE VIEW inner_join AS".
Donc le code SQL de création d'une vue est : CREATE view nomVue As SELECT ...
Il suffit ensuite de cliquer sur le bouton "exécuter".
Observez l'arborescence de la base ; le dossier "vues" comprend désormais une vue nommée "inner_join".
Ci-dessous l'état ayant pour source la vue "inner_join".
Notez que désormais la date du billet, son titre et son contenu ne sont affichés qu'une fois même si il y a N commentaires pour ce billet.
Notez la simplicité de l'instruction PHP qui appelle la requête : SELECT * FROM inner_join
On manipule la vue "inner_join" comme une table.
On n'a plus à se préoccuper de la sélection des champs, du type de jointure, de l'ordre des enregistrements.
Tout est géré en amont.
Concernant l'état remarquez l'astuce pour que certains champs de la vue ne soient affichés qu'une fois.
Au premier passage dans la boucle $precedent vaut 0 alors que $idb vaut 2
donc affichage de tous les champs de l'enregistrement.
Par contre au deuxième passage $precedent vaut 2 et $idb vaut toujours 2 donc égalité et donc affichage seulement
des champs $auteur & $commentaire.
À vous de 'bosser' !
Je vous propose de tester vos connaissances en réalisant des requêtes des vues et des états sourcés sur ces vues.
Partez du code SQL des requêtes multi-tables sur "billets" & "commentaires" dans le chapitre sur les requêtes SELECT.
Bien évidemment pour simplifier le code vous utiliserez des alias de tables.
Les requêtes SELECT
L'injection SQL est une vulnérabilité de sécurité qui permet à des attaquants d'exécuter des requêtes SQL malveillantes sur une base de données MySQL.
Une injection SQL consiste à insérer du code SQL malveillant dans des champs de saisie. Ce code SQL sera ensuite exécuté par le moteur de base de données.
Les injections SQL c'est un sujet complexe.
Pour en savoir davantage, je vous invite à lire l'excellent article sur WIKIPEDIA :
Les injections SQL
Cet article est excellent car il est illustré d'exemples.
Pour se protéger contre les injections SQL avec MySQL, il est recommandé d'utiliser des requêtes préparées ('Prepared Statements') afin de bien séparer le code SQL des données utilisateur.
La page "recherche_inscrits.php" est mise à la disposition de l'administration du site afin de retrouver rapidement un inscrit
en saisissant son identifiant (adresse mail).
Cette page a pour source une requête paramétrée préparée.
Dans la realité la table "inscrits" comprendra des milliers voire des dizaines de milliers d'enregistrements.
Comme la recherche se fait sur l'identifiant et que cette colonne est clé primaire, la recherche sera implicitement indexée.
Une clé primaire est un type d'index qui garantit l'unicité et la non-nullité des valeurs.
Dans une requête paramétrée ordinaire on aurait écrit : $bdd->query("SELECT * FROM inscrits WHERE identifiant = '$_GET['identifiant]' ");
Dans une requête préparée il y a une phase de préparation avec la méthode prepare()
$requete = $bdd->prepare('SELECT * FROM inscrits WHERE identifiant = ? ');
La partie variable de la requête est représentée par le symbole "?" (un marqueur).
Phase 2 : exécution de la requête préparée : $requete->execute(array($_GET['identifiant']));
La requête est alors exécutée grâce aux paramètres passés sous forme d'un 'array'.
Rappel du contenu de la table 'inscrits' :
INSERT INTO `inscrits` (`identifiant`, `motpasse`, `nom`, `prenom`, `date_naiss`) VALUES
('dupont@free.fr', 'zoro5362', 'Dupont', 'Julien', '1955-10-17'),
('dupuis@aol.com', 'sesame59', 'Dupuis', 'Léon', '1965-10-17'),
('lecornu@matignon.fr', 'censure26', 'Lecornu', 'Sébastien', '1975-10-17'),
('macron@elysee.com', 'toxique75', 'Macron', 'Emmanuel', '1985-10-17');
Saisissez l'un des identifiants et observez.
Dans le chapitre 27 (les requêtes sélection) je l'avoue, je vous ai menti.
Pour la connexion d'un inscrit à son espace perso je vous ai proposé une code ouvert aux injections SQL ;
une requête sélection paramétrée ordinaire :
SELECT * FROM inscrits WHERE identifiant = '$identifiant_saisi' AND motpasse ='$motpasse_saisi'
En fait le véritable code qui prévient des injections SQL est :
Notez qu'il y a deux marqueurs dans la requête préparée donc pour l'exécuter il faut deux élements à la fonction array()