1

I have defined my database table names as constants in a base class and use them throughout my code.

protected const MAP_KEY_TABLE = 'eds_map_keys';

If I use them like this I get a warning to use place holders.

$keys   = $wpdb->get_results(
        'SELECT * FROM ' . self::MAP_KEY_TABLE . ' WHERE key_type = "map_key"',
        OBJECT
    );
    $mapkey = $keys[0]->key_value;

if I use place holders like this:

$keys = $wpdb->get_results(
        $wpdb->prepare(
            'SELECT * FROM %1s WHERE key_type = "geo_key";',
            self::MAP_KEY_TABLE
        ),
        OBJECT
    );  // db call ok.
    $map_key_geo = $keys[0]->key_value;

I get a warning that: "message": "Complex placeholders used for values in the query string in $wpdb->prepare() will NOT be quoted automagically. Found: %1s."

As suggested in a comment I tried $1$s but the warning still persists.

WP Version 6.1.1, PHP Version 8.0.18, PHP_CodeSniffer version 3.7.1

I don't know if the guidelines are version specific but they were installed like this.

composer require --dev wp-coding-standards/wpcs
composer require --dev dealerdirect/phpcodesniffer-composer-installer

I'd really like to get rid of the messages about coding style but have been stuck on this one for a while. Any suggestions greatly appreciated.

7
  • "if I use place holders like this" - what's the PHP code you used; I couldn't find it in your question. But I don't see why would you get a warning when your query doesn't include dynamic variables (e.g. WHERE key_type = '$type'). And you could also instead assign the table name to a local variable and then use "SELECT * FROM $table WHERE key_type = 'map_key'" ?
    – Sally CJ
    Commented Feb 19, 2023 at 5:43
  • I added the code that causes the error. @SallyCJ I agree that this shouldn't cause an error when using static data, but it does. If there isn't a better solution, I'm leaning towards using a local variable as you pointed out. What is more baffling is why it cares to mention the quoting thing? Possibly there is some kind of badness that can happen if it isn't quoted that I'm not aware of.
    – xsoftie
    Commented Feb 19, 2023 at 15:10
  • I could answer that, but then it sounded like you're using an old(er) version of WordPress, so what version of WordPress and PHP are you using - maybe you should add that to your post/question? Also, FYI, the correct numbered format is %1$s (note the $) and not %1s, which is what you used. (yes, %1s may have worked for you, but that does not mean it's correct)
    – Sally CJ
    Commented Feb 20, 2023 at 3:26
  • So this is actually about phpcs and wpcs (I thought those were warnings added by WordPress to the debug log like wp-content/debug.log), and apparently, you need to do $wpdb->eds_map_keys = self::MAP_KEY_TABLE; (in the class constructor), which then allows these queries: "SELECT * FROM $wpdb->eds_map_keys WHERE key_type = 'map_key'" and $wpdb->get_results( $wpdb->prepare( "SELECT * FROM $wpdb->eds_map_keys WHERE key_type = %s", 'map_key' ) );, without getting those "Complex placeholders" warnings.
    – Sally CJ
    Commented Feb 21, 2023 at 5:56
  • But IMO, FROM $wpdb->eds_map_keys, FROM $table and FROM ' . self::MAP_KEY_TABLE . ' are the same (the table names could all be considered not safe).. so maybe it's wpcs which is being a little too strict... anyway, see Ignoring Parts of a File and Whitelisting code which flags errors, and be sure to tag me if you replied or edited your post :)
    – Sally CJ
    Commented Feb 21, 2023 at 6:13

1 Answer 1

0

I'd really like to get rid of the messages about coding style

Despite not recommended, you can ignore/whitelist warnings and errors for a line or block of code using special PHPCS/WPCS comments which you can find here:

Working examples: ( Note: WordPress accepts all these syntaxes without giving any errors/warnings, however, it's WPCS which does not accept them 😅 )

A better solution, or a trick, which does not result in those warnings/errors

  1. Add the table name as a property in the global $wpdb object, i.e. $wpdb->eds_map_keys = self::MAP_KEY_TABLE;.

  2. Then use that in your SQL commands, e.g. FROM $wpdb->eds_map_keys.

This works because WPCS allows $wpdb->. (Otherwise, you would not be able to use $wpdb->posts, $wpdb->postmeta, $wpdb->terms, etc. which references the core tables in WordPress)

However, note that $this->eds_map_keys (which could be a private property) or $some_other_object->eds_map_keys will not work, i.e. not accepted by WPCS.

Additional Notes regarding the first parameter for $wpdb->prepare()

  1. The documentation stated that "for compatibility with old behavior, numbered or formatted string placeholders (eg, %1$s, %5s) will not have quotes added by this function, so should be passed with appropriate quotes around them".

    And unfortunately, at the time of writing, WPCS will not accept them when used for table names, e.g. FROM %1$s or FROM `%1$s` will result in the UnquotedComplexPlaceholder error.

  2. The correct argument swapping format is %<number>$s (note the $) and not %<number>s. So as I commented, you should use %1$s instead of %1s.

    See the PHP manual for more details.

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.