How to properly sanitize strings without $wpdb->prepare?

I can’t use $wpdb->prepare, since I want to be able to add variables
to my query string that look something like:

$var = "AND pm.meta_value="%$_POST["val']%'";

To get a literal % to pass through $wpdb->prepare just double it. You don’t need to be avoiding $wpdb->prepare.

Proof of concept:

var_dump($wpdb->prepare('SELECT * FROM {$wpdb->posts} WHERE post_title LIKE "%%%s%%"','Hello'));

A comment below suggests something a bit more complicated might be in order:

$var[] = 'post_title LIKE "%%%s%%"';
$var_data[] = 'Hello';
$var[] = 'post_name LIKE "%%%s%%"';
$var_data[] = 'Hi';
$var[] = 'post_date LIKE "%%%s%%"';
$var_data[] = 'Howdy';
var_dump($wpdb->prepare('SELECT * FROM {$wpdb->posts} WHERE post_title '.implode(' AND ',$var),$var_data));

Of course, in practice you would probably create $var and $var_data in some kind of loop such as:

foreach ($_POST as $k=>$v) {
  if ('abc' == $k) {
    $var[] = 'post_title LIKE "%%%s%%"';
    $var_data[] = $v; // should probably validate a bit
  } elseif(...) {
    // ...
  } else {
    // ...
  }
}

It is always possible to run prepare on each item as well:

$var[] = $wpdb->prepare('post_title LIKE "%%%s%%"','Hello');

But the method using the array strikes me as more elegant and only runs $wpdb->prepare once, for what that is worth.

Leave a Comment