3rd party dependency conflict in developing Wordpr

2019-03-02 05:24发布

问题:

I am developing a plugin that used composer.. meaning it has a vendor folder inside the plugin folder which includes Guzzle HTTP dependency

On wordpress site we installed this plugin, there is an existing plugin that has Guzzle HTTP

Now when we activate this plugin i am getting an error something like this:

Fatal error: Cannot redeclare GuzzleHttp\uri_template() (previously declared in /nas/content/staging/project/wp-content/plugins/my-plugin/vendor/guzzlehttp/guzzle/src/functions.php:17) in /nas/content/staging/project/wp-content/plugins/other-plugin/includes/lib/aws-sdk/GuzzleHttp/functions.php on line 31

I tried installing Plugins Load Order to force the 'other-plugin' to load first before 'my-plugin' currently the error is happening on the other-plugin's resources. this way, The error will yield in our autoload and we can catch that.

unfortunately.. Plugins Load Order did not work..

any ideas how to solve this?

回答1:

Welcome to WordPress hell. We have 2018 and WordPress still does not have any dependency management and still didn't notice Composer existence.

WordPress ecosystem simply relies on assumption, that functions/classes names of plugins/themes should be unique. Obviously distributing popular 3rd-part Composer libraries with your plugin/theme is asking for trouble - it is easy to get names collision when other plugin is doing the same. There is no good way out of this situation.

If you want a bulletproof solution for standalone plugins, you should prefix namespaces of every package in your vendor directory with plugin prefix, for example myplygin\vendor. Then GuzzleHttp\Client becomes myplugin\vendors\GuzzleHttp\Client, so there is no risk of name collisions. This will require some work to write script for this (or you may use some existing solutions, like humbug/php-scoper), and you may get many duplicated dependencies (10 plugins may bring the same library 10 times, but with different namespaces), but this is the cost of integrating modern tools and patterns into outdated software.

If you're writing this plugin for yourself and you're controlling final installation, you may try to use Composer for installing WordPress and its plugins. You still may need to fix 3rd-party plugins (via forking) if they're have bundled some composer library, but in the long run it should simplify many things and you may avoid duplicating libraries for every plugin.



回答2:

This is not suggested but use it if you must

function this_plugin_last() {
    $wp_path_to_this_file = preg_replace('/(.*)plugins\/(.*)$/', WP_PLUGIN_DIR."/$2", __FILE__);
    $this_plugin = plugin_basename(trim($wp_path_to_this_file));
    $active_plugins = get_option('active_plugins');
    $this_plugin_key = array_search($this_plugin, $active_plugins);
        array_splice($active_plugins, $this_plugin_key, 1);
        array_push($active_plugins, $this_plugin);
        update_option('active_plugins', $active_plugins);
}
add_action("activated_plugin", "this_plugin_last");


回答3:

I'm guessing there's a function at GuzzleHttp/functions.php on line 31 so you can use something like that:

  if (function_exists('Do_Something')){
       echo "Function Exists"; 
    }else{
       echo "Function Not Found, This name Can be used!";
    }

or you can use is_plugin_active function to check if the plugin is already installed. In that case, you can ignore including the files

https://codex.wordpress.org/Function_Reference/is_plugin_active