Skip to content


VIP notices are best practice recommendations, often for code maintenance or minimizing error logs. These issues should be addressed, but are unlikely to cause a performance or security problem in production environments.

Check for is_array(), !empty() or is_wp_error()

Before using a function that depends on an array, always check to make sure the arguments you are passing are arrays. If not, PHP will throw a warning.

Recommended example:

$tags_array = get_the_terms( get_the_ID(), 'post_tag');
//get_the_terms function returns array of term objects on success, false if there are no terms or the post does not exist, WP_Error on failure. Thus is_array is what we have to check against
if ( is_array( $tags_array ) ) {
    $tags = wp_list_pluck( $tags_array , 'name');

Not recommended:

$tags = wp_list_pluck( get_the_terms( get_the_ID(), 'post_tag') , 'name');

Common functions/language constructs that are used without checking the parameters beforehand: foreach(), array_merge(), array_filter(), array_map(), array_unique(), wp_list_pluck()
Always check the values passed as parameters or cast the value as an array before using them.

Using in_array() without strict parameter

PHP handles type juggling. This also applies to in_array(), meaning that this:

in_array( 0, ['safe_value', 'another string']);

Will return true.

Inline resources

Inlining images, scripts, and styles has been a common workaround for performance problems related to HTTP 1.x As more and more of the web is now served via newer protocols (SPDY, HTTP 2.0), these techniques are now detrimental as they cannot be cached, and must be sent every time with the parent resource.

Using == instead of ===

PHP handles type juggling. Meaning that this:

$var = 0;
if ( $var == 'safe_string' ){
    return true;

Will return true. VIP recommends using === over ==.

Other interesting things that are equal are:

  • (bool) true == 'string'
  • null == 0
  • 0 == '0SQLinjection'
  • 1 == '1XSS'
  • 0123 == 83 (here 0123 is parsed as an octal representation)
  • 0xF == 15 (here 0xF is parsed as a hexadecimal representation of a number)
  • 01 == '1string'
  • 0 == 'test'
  • 0 == ''

Using output buffering

Only use output buffering when truly necessary, always in the same scope and not with conditionals. Never use output buffering in a context where it is called conditionally or across multiple functions/classes.

Not defining post_status or post_type

By default, the post_status of a query is set to publish for anonymous users on the front end. It is not set in any WP_ADMIN context, including Ajax queries. Queries on the front end for logged-in users will also contain an OR statement for private posts created by the logged-in user, even if that user is not part of the site. This will reduce the effectiveness of MySQL indexes, specifically the type_status_date index.

The same is true for post_type. If you know that only a certain post_type will match the rest of the query (for example, for a taxonomy, meta, or just general query), adding the post_type as well as the post_status will help MySQL better utilize the indexes at its disposal.

Using closing PHP tags

As part of the WordPress Coding Standards, all PHP files should omit the closing PHP tag to prevent an accidental output of whitespace and other characters, which can cause issues such as ‘Headers already sent‘ errors.

Use wp_json_encode() over json_encode()

wp_json_encode() will ensure the string is valid UTF-8, while the regular function will return false if it encounters invalid UTF-8. It also supports backward compatibility for versions of PHP that do not accept all the parameters.

Caching large values in options

Memcached has a 1 MB cache key limit. Anything above is not stored and will be directly read from the DB.


For multisite instances, switch_to_blog() only switches the database context, not the code that would run for that site (e.g. different filters).

Last updated: September 06, 2023

Relevant to

  • WordPress