56

I'd like to use a LIKE %text% statement while still using the WordPress $wpdb class to sanitize and prepare input.

SELECT column_1 from `prefix_my_table` WHERE column_2 LIKE '%something%';

I've tried something like this to no avail:

$wpdb->prepare( "SELECT column_1 from `{$wpdb->base_prefix}my_table` WHERE column_2 LIKE %s;", like_escape($number_to_put_in_like));

How do you properly prepare a %LIKE% SQL statement using the WordPress database class?

4 Answers 4

82

The $wpdb->esc_like function exists in WordPress because the regular database escaping does not escape % and _ characters. This means you can add them in your arguments to wpdb::prepare() without problem. This is also what I see in the core WordPress code:

$wpdb->prepare(" AND $wpdb->usermeta.meta_key = '{$wpdb->prefix}capabilities' AND $wpdb->usermeta.meta_value LIKE %s", '%' . $this->role . '%');

So your code would look like:

$wpdb->prepare(
    "SELECT
        column_1
    FROM
        `{$wpdb->base_prefix}my_table`
    WHERE
        column_2 LIKE %s;",
    '%' . $wpdb->esc_like($number_to_put_in_like) . '%'
);

You can also add %% in your query to get a literal % (wpdb::prepare() uses vsprintf() in the background, which has this syntax), but remember that your string will not be quoted, you must add the quotes yourself (which is not what you usually have to do in wpdb::prepare().

4
  • what are the {} for ? Commented Aug 20, 2014 at 22:39
  • @FranciscoCorralesMorales: To indicate that everything inside it should be considered a variable expression, otherwise it would only see $wpdb, and ignore the ->prefix after it.
    – Jan Fabry
    Commented Aug 21, 2014 at 15:14
  • 1
    @JanFabry Close. I would correct the comment to say: "... otherwise it would see all of $wpdb->base_prefixmy_table and try to to look up base_prefixmy_table property instead of just base_prefix.
    – Flimm
    Commented Oct 10, 2017 at 9:24
  • Also a thing to mention is that the % are being replaced by a stupidly long hash. Which does look wrong when you var_dump the sql output. After hours of searching its noted here that this is a Wordpress 4.8.3 security fix for sql injection. stackoverflow.com/a/57914094/7977916 Commented Jan 4, 2022 at 20:26
10

You need to double percent so they are no treated like fragment markers by wpdb->prepare():

$wpdb->prepare( "SELECT column_1 from `{$wpdb->base_prefix}my_table` WHERE column_2 LIKE %%%s%%;", $wpdb->esc_like( $number_to_put_in_like));

PS not sure this is best/only way to do it.

3
  • 5
    Remember that you must add the quotes around the string yourself, because wpdb::prepare will only add them for a %s that is not preceded by an %. The final part of your query should be WHERE column_2 LIKE '%%%s%%'.
    – Jan Fabry
    Commented Feb 8, 2011 at 9:39
  • 1
    This worked great along with @JanFabry 's tip
    – Gavin
    Commented Oct 31, 2021 at 10:32
  • Liked this answer best due to use of esc_like and @JanFabry 's comment.
    – Tami
    Commented Jun 18, 2022 at 13:06
2

This is one way to do it that I've checked and it works:

$search_text = "%" . $_GET['some_text'] . "%";

$user_count = $wpdb->get_var( 
    $wpdb->prepare( 
        "SELECT COUNT(*) FROM mix_library WHERE ml_setting_name LIKE %s", 
        $search_text 
    ) 
);

Replace variables to suit your needs.

1
1
$safe_sql = $wpdb->prepare("SELECT * FROM $wp_track_table $sql",["*yoursecretkey*".$_POST['search']."*yoursecretkey*"]);

$safe_sql = str_replace("*yoursecretkey*", "%", $safe_sql);

I found a suitable solution with the above codes. Definitely try it.

2
  • 1
    So your approach is to pass a random string into prepare() and replace that with percents afterwards? That feels like you're fighting WordPress.
    – Rup
    Commented Sep 23, 2022 at 11:46
  • Basically templating, I suppose. Not the cleanest, but certainly one approach! Thank you.
    – editor
    Commented Sep 23, 2022 at 21:15

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.