Since WP3.5, prepare() accepts placeholders as a security measure, instead of just appending the argument to the query. Therefore, $wpdb->prefix needs to become a second parameter, called by %s:

$count = $wpdb->get_var( $wpdb->prepare( "SELECT COUNT(id) FROM %s WHERE answer !=' '", $wpdb->prefix . "faq_questions" ) );  

However, doing that returns the table name in quotes:

SELECT COUNT(id) FROM 'wp_faq_questions' WHERE answer !=' '

How can I fix this?


How can I fix this?

You can't, but it isn't broken. You are telling prepare to use a string. A string will be quoted. It isn't meant to generate MySQL syntax, which is what you are asking it to do. Your tablename is more a MySQL command or keyword than a string value. That isn't what prepare is for.

prepare is meant to operate on user supplied data. Your tablename is not-- well, shouldn't be-- user supplied data so you don't need to "prepare" it. It is unnecessary. Just construct the tablename in the SQL itself:

"SELECT COUNT(id) FROM ".$wpdb->prefix."faq_questions WHERE answer !=' '"

See: https://wordpress.stackexchange.com/a/93861/21376


You have some choices. Whitelisting is a good option - that is, check against an array of allowed field names and only add the ORDERBY clause if one of the field names is recognized.

if ( in_array( $table_name, ['faq_questions', 'faq_responses', 'some_other_table'] ) )...

Otherwise, WordPress has a nice function built just for you: https://codex.wordpress.org/Function_Reference/sanitize_sql_orderby

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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