Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WP-CLI can fail cryptically when parsing custom wp-config.php #1631

Closed
danielbachhuber opened this issue Jan 28, 2015 · 22 comments
Closed

WP-CLI can fail cryptically when parsing custom wp-config.php #1631

danielbachhuber opened this issue Jan 28, 2015 · 22 comments

Comments

@danielbachhuber
Copy link
Member

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.

@szepeviktor
Copy link
Contributor

Does this if prevent this behaviour?

@nextgenthemes
Copy link

Fatal error: Call to undefined function add_filter() in phar:///home/xxxxxx/bin/wp/php/wp-cli.php(23) : eval()'d code on line 92

I am on webfaction if that matters. And I use Q2A WP intergration, so i have the following added to my wp-config.php (start and end)

<?php
/**
 * The base configurations of the WordPress.
 *
 * This file has the following configurations: MySQL settings, Table Prefix,
 * Secret Keys, WordPress Language, and ABSPATH. You can find more information
 * by visiting {@link http://codex.wordpress.org/Editing_wp-config.php Editing
 * wp-config.php} Codex page. You can get the MySQL settings from your web host.
 *
 * This file is used by the wp-config.php creation script during the
 * installation. You don't have to use the web site, you can just copy this file
 * to "wp-config.php" and fill in the values.
 *
 * @package WordPress
 */

define('COOKIEPATH', '/');
define('COOKIE_DOMAIN', '.nextgenthemes.com');

--- normal config removed ---

add_filter('allowed_redirect_hosts', 'qa_wordpress_redirect_hosts');
function qa_wordpress_redirect_hosts($content) {
    $content[] = 'community.nextgenthemes.com';
    return $content;
}

@szepeviktor
Copy link
Contributor

Try moving add_filter () to a MU plugin. It can be used after WP core is loaded.

@nextgenthemes
Copy link

@szepeviktor Awesome thanks, I somehow guessed this but did ask b4 thinking of mu-plugins.

@EndemolUK
Copy link

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.

@bloqhead
Copy link

@EndemolUK that actually worked for me as well. Thank you!

a7127cff69cab32e5c4723e8446e21c4b7325dc added a commit to a7127cff69cab32e5c4723e8446e21c4b7325dc/wp-cli that referenced this issue Sep 23, 2015
Only include definitions and variable declarations in the wp-config $lines_to_run.  This should resolve problems seen with wp-cli#1631
@scribu
Copy link
Member

scribu commented Sep 25, 2015

@rmccue shared a great solution:

Instead of hacking the contents of the wp-config.php file and then calling eval() on it, just define ABSPATH to point to an empty wp-settings.php file:

https://github.com/humanmade/Cavalcade-Runner/blob/26054b4a302f2e59972115a5c24916d24873601f/lib/Runner.php#L28-L52

@rmccue
Copy link
Contributor

rmccue commented Sep 25, 2015

Note: if you need to load WP afterwards, this can break, since WP needs to know the right ABSPATH to load itself, and plugins will also depend on that. I don't think that matters in some places wp-cli loads it, but potentially some it does.

To help with that, you can use a hybrid solution: fork/exec off an instance just to load the config, have it output as JSON, then use that in your main process. The overhead of doing that is reasonably minimal (since you're only loading wp-config, not all of WP), but it does exist.

@scribu
Copy link
Member

scribu commented Sep 25, 2015

Ah... I think WP-CLI already uses the fake ABSPATH trick when it doesn't need to load the rest of WP.

fork/exec off an instance just to load the config, have it output as JSON, then use that in your main process.

Yeah, I guess you could detect (in a generic way) all the constants and globals that wp-config sets and send them via JSON.

@rmccue
Copy link
Contributor

rmccue commented Sep 25, 2015

Yeah, I guess you could detect (in a generic way) all the constants and globals that wp-config sets and send them via JSON.

You can basically just use get_defined_vars and get_defined_constants before/after loading for that. Works reasonably well.

@danielbachhuber
Copy link
Member Author

Related #2278

@danyalette
Copy link

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)

@benlk
Copy link

benlk commented Jun 6, 2016

If it's any use diagnosing this bug, the described behavior does not occur when run with the --debug flag, using Wordpress 4.5.2 and a Wordpress-generated wp-config.php:

vagrant@precise64:/vagrant$ wp --debug
Debug: No readable global config found (0.02s)
Debug: No project config found (0.023s)
Debug: No package autoload found to load. (0.04s)
Debug: ABSPATH defined: /vagrant/ (0.041s)
Debug: Begin WordPress load (0.044s)
Debug: wp-config.php path: /vagrant/wp-config.php (0.045s)
Debug: Loaded WordPress (2.491s)
Debug: Running command: help (2.596s)

and then I pressed q to exit the help list.

Running without --debug::

vagrant@precise64:/vagrant$ wp
PHP Fatal error:  Call to undefined function apply_filters() in /vagrant/wp-includes/load.php on line 315

System information:

vagrant@precise64:/vagrant$ php --version
PHP 5.3.10-1ubuntu3.23 with Suhosin-Patch (cli) (built: May 19 2016 20:38:03) 
Copyright (c) 1997-2012 The PHP Group
Zend Engine v2.3.0, Copyright (c) 1998-2012 Zend Technologies

vagrant@precise64:/vagrant$ uname -a
Linux precise64 3.2.0-23-generic #36-Ubuntu SMP Tue Apr 10 20:39:51 UTC 2012 x86_64 x86_64 x86_64 GNU/Linux

@danielbachhuber
Copy link
Member Author

@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.

@benlk
Copy link

benlk commented Jun 8, 2016

That's not quite what happened, but you're right that that install was using the master branch of https://github.com/wordpress/wordpress. Thanks! I'll downgrade it to 4.5.2.

(https://github.com/INN/deploy-tools has a command fab wp.install, which I ran without the required version number argument, which downloaded the master branch of wordpress instead of failing. I'm not using VVV)

@danielbachhuber
Copy link
Member Author

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.

@senica
Copy link

senica commented Feb 21, 2017

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.

@decadence
Copy link

decadence commented Aug 8, 2017

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

@temujin9
Copy link

temujin9 commented Jan 17, 2018

Any chance that add_filter could be defined as a no-op fuction in this context, so that WP CLI can be used without requiring modifications? (EDIT: apparently, no. I'd forgotten that you can't redefine functions in PHP.)

@paulschreiber
Copy link

I hit this because the last two lines in my wp-config weren't the expected:

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

@nickbreen
Copy link

@decadence your comment led me to my fix. I had <?Php rather than <?php at the start of wp-config.php.

The cryptic error message in my case was:

PHP Parse error:  syntax error, unexpected '<', expecting end of file in phar://
/usr/local/share/php/wp-cli.phar/php/WP_CLI/Runner.php(941) : eval()'d code on line 1

Which, of course, implies some PHP file has a syntax error.

@decadence
Copy link

@nickbreen glad you solved it

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests