web-dev-qa-db-fra.com

Est-ce que $ wpdb-> prepare s'échappe trop? Comment l'utiliser correctement?

Je suis assez confus par $ wpdb-> prepare. Je veux l'utiliser pour effacer les entrées de l'utilisateur, mais il s'est avéré que cela détruit la requête. Je ne peux pas imaginer que c'est comme ça que ça fonctionne, mais je ne peux pas savoir ce que je fais mal. S'il vous plaît soyez si patient et pointez-moi vers la solution. Le code suivant est juste un exemple simple à des fins de démonstration, juste pour expliquer ce qui ne va pas et comment. Plus tard, il y aura une entrée utilisateur alimentant cette requête.

Lorsque j'ai omis de préparer et d'utiliser sprintf à la place, cet exemple fonctionne:

global $wpdb;
$mydb = new \wpdb( "My_Login" ,"My_PW" , "My_Custom_DB" ,"localhost"); //wpdb instance for my custom db

$tablename = "books";
$sort_direction = "DESC";
$limit = 5;   
$sqlquery = sprintf( "SELECT * FROM %s ORDER BY datum %s LIMIT %d", $tablename, $sort_direction, $limit );

$res = $mydb->get_results( $sqlquery );
echo "<br>".$sqlquery."<br>";
var_dump($res);

La sortie de var_dump () est un tableau approprié contenant le résultat attendu.

La sortie de $ sqlquery est:

SELECT * FROM books ORDER BY datum DESC LIMIT 5

Quel est le bon SQL.

Maintenant, je vais utiliser prepare (c'est la seule ligne modifiée):

global $wpdb;
$mydb = new \wpdb( "My_Login" ,"My_PW" , "My_Custom_DB" ,"localhost"); //wpdb instance for my custom db

$tablename = "books";
$sort_direction = "DESC";
$limit = 5;   
$sqlquery = $mydb->prepare( "SELECT * FROM %s ORDER BY datum %s LIMIT %d", $tablename, $sort_direction, $limit );

$res = $mydb->get_results( $sqlquery );
echo "<br>".$sqlquery."<br>";
var_dump($res);

La sortie de var_dump () estNULL

La sortie de $ sqlquery est:

SELECT * FROM 'books' ORDER BY datum 'DESC' LIMIT 5

Le nom de la table et DESC ne doit évidemment pas être placé entre guillemets. OMI c'est la raison pour laquelle il échoue. J'ai vérifié deux fois que cela n'était pas lié à l'instanciation de $ wpdb. Lorsque je travaille avec $ wpdb, le résultat d'échappement est le même.

Qu'est-ce qui se passe ou qu'est-ce que je me suis trompé? Aidez-moi, s'il vous plaît.

2
Hexodus

Ce que vous avez fait de mal ici, c'est de préparer ces articles en premier lieu.

Vous exécutez uniquement les variables "data" via prepare (). Vous n'exécutez pas de noms de tables, ne triez pas les directions ou ne les limitons pas. Celles-ci font partie de la commande SQL elle-même, ce ne sont pas des données qui font référence à des informations stockées dans une colonne de la base de données.

Votre requête SELECT ne contient aucune entrée de données ... par conséquent, aucune entrée ne peut être préparée.

Dans le cas spécifique d'un SELECT, les données sont le contenu de la clause WHERE. colonne =% s et ainsi de suite. Il s’agit d’un élément de données variable qui peut être potentiellement dangereux car il provient peut-être d’une entrée de l’utilisateur. Donc, ces données doivent être passées en revue pour être sécurisées. Mais si vous avez un "DESC" codé en dur pour la commande, il ne sert à rien de l'exécuter. C'est "DESC". C'est sécuritaire tel quel. Seules les données dont vous ne savez pas ce que c'est peuvent être dangereuses.

Edit: Cela dit, si les données proviennent de la saisie de l'utilisateur, par exemple si l'utilisateur peut sélectionner le nombre d'éléments à afficher, ces données doivent alors être effacées. Donc, les limites peuvent être passées par prepare car elles sont entières et peuvent provenir d'un utilisateur sélectionnant "5" ou "10".

Cependant, vous ne permettriez pas à un utilisateur de saisir directement le nom de la table ou l'ordre de tri. Ils choisiraient une direction pour afficher les choses, mais vous convertiriez cela en ASC ou en DESC. Ils ne choisiraient pas "des livres" directement, mais pourraient choisir dans une liste que vous interprétez comme "des livres". Ce genre de chose.

3
Otto