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.