Si vous voulez minimiser les risques d’injection SQL il faut utiliser PDO, n’utilisez plus Mysqli. Dites lui non svp.
Connexion à la base de données:
On est en programmation orientée objet donc utilisez le mot clé new
pour instancier une connexion à une base de données.
$pdo = new \PDO($dsn, $user, $pass)
$dsn
est une chaine qui défini une ressource de base de données,
$dsn = 'mysql:host=localhost;dbname=votre_base';
Lancer une requête SQL:
$sql = 'SELECT * FROM table';
$stmt = $pdo->prepare($sql);
Avec PDO vous utilisez des requêtes préparées (prepared statement), et ensuite on exécute
$stmt->execute();
et pour retirer les résultats :
$result = $stmt->fetchAll();
Je sais que vous êtes un programmeur curieux, donc vous allez voir la tête de l’objet retourné. Les données ne sont pas bonnes mais c’est pour vous donner la structure du tableau retourné.
Array
(
[0] => Array
(
[id_site] => 10
[0] => 10
[domaine] => www.google.fr
[1] => www.google.fr
)
)
On remarque que dans l’élément les informations sont doublées mais indexés de façon différent, on a les index numériques et les index alphanumériques.
PDO vous donne en fait le choix de travailler soit avec les tableaux associatifs soit les tableaux classiques.
Si ce sont les champs nommés du tableau associatif qui vous intéressent :
$result = $stmt->fetchAll(PDO::FETCH_ASSOC); // retourne un tableau associatif
$result = $stmt->fetchAll(PDO::FETCH_CLASS); // retourne une classe
$result = $stmt->fetch(PDO::FETCH_ASSOC); // retourne un seul résultat
Les requêtes préparées avec PDO
Avec les requêtes préparées, vous devez écrire une requêtes SQL avec des paramètres à l’intérieur et pas des variable PHP. L’intérêt est qu’avec ce genre de requêtes, vous vous évitez la plupart des injections SQL et aussi accessoirement les problèmes d’échappement de caractères spéciaux.
Requête PDO SQL avec une clause WHERE
Regardons comment on fait une requête plus évoluée:
$stmt->prepare('SELECT * FROM table WHERE id = :id');
$stmt->bindParam(':id',$id,PDO::PARAM_INT);
$stmt->execute();
Ici on met un masque dans la clause where et ensuite on attribue une valeur au masque, c’est ici tout l’intérêt de PDO (il y en a d’autres),
paramétrer la requête SQL de cette façon évite les injection SQL. On indique aussi quel est le type de variable on passe
On peut passer aussi par valeur au lieu d’une variable php
$stmt->bindValue(':id',50);
Une autre façon de passer des paramètres est d’utiliser des points d’interrogation
$stmt->prepare('SELECT * FROM table WHERE id = ?');
$stmt->bindValue(1,50,PDO::PARAM_INT);
Ici l’indice 1 correspond au premier point d’interrogation, quand vous en avez deux vous aurez un sur le premier bind et deux sur le second bind.
Insertion avec les requêtes préparées
Le principe des requêtes préparées est de ne pas mettre les valeurs à insérer directement dans la requêtes SQL, mais de les remplacer par des alias (placeholder) que l’on va populer ensuite.
#la requête SQL modifiée
$sql = "INSERT INTO users (nom, prenom, age) VALUES (:nom, :prenom, :age)";
#les paramètres à insérer sont mis dans un tableau
$params = ['nom' => $nom,'prenom' => $prenom,'age' => $age];
#on exécute la requête
$stmt = $pdo->prepare($sql);
$stmt->execute($params);
#placeholder non nommé, dans ce cas respectez l'ordre
$sql = "INSERT INTO users (nom, prenom, age) VALUES (?,?,?)";
Mise à jour avec les requêtes préparées
$sql = "UPDATE users SET name=?, surname=?, sex=? WHERE id=?";
$stmt= $pdo->prepare($sql);
$stmt->execute([$name, $surname, $sex, $id]);
ou
$sql = "UPDATE users SET name=?, surname=?, sex=? WHERE id=?";
$pdo->prepare($sql)->execute([$name, $surname, $sex, $id]);
Avec les paramètres nommés
$data = [
'name' => $name,
'surname' => $surname,
'sex' => $sex,
'id' => $id,
];
$sql = "UPDATE users SET name=:name, surname=:surname, sex=:sex WHERE id=:id";
$stmt= $pdo->prepare($sql);
$stmt->execute($data);
ou
$sql = "UPDATE users SET name=:name, surname=:surname, sex=:sex WHERE id=:id";
$pdo->prepare($sql)->execute($data);
Retourner le nombre d’occurences
$sql = "SELECT count(*) FROM `table` WHERE foo = bar";
$result = $con->prepare($sql);
$result->execute();
$number_of_rows = $result->fetchColumn();
Retourner le dernier id de la clé primaire (auto généré)
C’est vraiment très pratique, pas la peine de refaire un SELECT qui n’a d’ailleurs aucune garantie de retourner l’id de votre insertion si il y a beaucoup d’opérations d’insertion.
$sql = "INSERT INTO rendu (user_id,questionnaire_id) VALUES (:user_id,:questionnaire_id)";
$params = [
'user_id' => $user_id,
'questionnaire_id' => $questionnaire_id,
];
$stmt = $pdo->prepare($sql);
$result = $stmt->execute($params);
$id = $pdo->lastInsertId();
Echo des erreurs
Comme il n’est pas possible de voir à quoi va ressembler la requête finale, vous devez afficher le résultat de la requête ou de la préparation
$stmt = $pdo->prepare($sql);
if(!$stmt){ print_r($pdo->errorInfo();}
#ou après l'exécution
$stmt = $pdo->prepare($sql)
$res = $stmt->execute($params);
print_r($stmt->errorInfo());