wp-cli: WP-CLI can fail cryptically when parsing custom wp-config.php

Starting a new issue as the definitive place to point users who’ve run into this.

WP-CLI uses a custom version of WordPress’s wp-settings.php file. Here’s a narrative version of the backstory. Before WP-CLI can load wp-settings-cli.php, it needs to know all of the constants defined in wp-config.php (database connection details and so on).

In a typical WordPress install, wp-config.php has the following at the end of the file:

/* That's all, stop editing! Happy blogging. */

/** Absolute path to the WordPress directory. */
if ( !defined('ABSPATH') )
    define('ABSPATH', dirname(__FILE__) . '/');

/** Sets up WordPress vars and included files. */
require_once(ABSPATH . 'wp-settings.php');

This is the code that loads WordPress. Because WP-CLI doesn’t want WordPress to load yet when it’s pulling the constants out of wp-config.php, it uses regex to strip the require_once(ABSPATH . 'wp-settings.php'); statement.

But, if the regex fails for whatever reason, WordPress gets loaded via the normal wp-settings.php statement when wp-config.php is evaluated, and WP-CLI can fail in a variety of cryptic ways.

About this issue

  • Original URL
  • State: closed
  • Created 9 years ago
  • Reactions: 3
  • Comments: 22 (9 by maintainers)

Commits related to this issue

Most upvoted comments

@benlk I think in time you did your before and after, VVV ran svn up on your /vagrant directory. The fatal error you’re seeing is from a filter introduced in WP 4.6, so you’ll need to run wp cli update --nightly for compatibility.

if you are using Pantheon and are having this issue (i.e. getting a seemingly random fatal error - à la Fatal error: Cannot redeclare wp_is_mobile() (previously declared in /path/vars.php:126) in phar:///usr/local/bin/wp/php/wp-settings-cli.php on line 271 when you attempt to use the wp cli): the require statement giving you trouble is in wp-config-local.php, not in wp-config.php .

I simply commented out require_once(ABSPATH . 'wp-settings.php'); in wp-config-local.php (and left it as-is in wp-config.php). This solved my wp-cli problem and doesn’t appear (so far) to have any adverse effects (since wp-settings.php does still get loaded in wp-config.php)

For those that got here because of the add_filter error, just wrap your add_filters in a if(function_exists('add_filter')){ /* your add_filter functions here */ } If you don’t want to move them to a plugin or some of the other suggested routes.

As a quick and simple fix then the following mod at the end of wp-config.php should always work I think?

Change:

/** Sets up WordPress vars and included files. */
require_once(ABSPATH . 'wp-settings.php');

To

if(!function_exists('wp_unregister_GLOBALS'))  {
    /** Sets up WordPress vars and included files. */
    require_once(ABSPATH . 'wp-settings.php');
}

This way if using wp-cli’s internal version of wp-settings.php we don’t load the site’s version, and the regex that wp-cli requires to work is preserved. If just running the site as normal it’ll still load too.

I don’t see this as a permanent answer to the issue but it works for me.

At this point, I think we’re going to stick with what we have. The approach of spawning a separate process to read wp-config.php is creative, but I’d be concerned about introducing a breaking change if there was business logic in the config file. While somewhat painful, this is a problem users are capable of fixing on their own.

It also fails if you have <? open tag in wp-config.php instead of <?php