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?
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.
By design, PHP and Composer assume that you develop and distribute your code in a controlled environment. However, when you publish plugins on WordPress or modules on Joomla, you distribute the code on systems where you don't have control over what other authors install. This situation can result in name collisions such as Cannot redeclare GuzzleHttp\uri_template()....
To prepare your code for multi-vendor setups, you must prefix the PHP code to avoid name collisions or version collisions (the same library with a different version is loaded first). For instance, Guzzle is a well-known and widely used library, so if you publish a plugin including it, you must prefix it before distribution.
At first glance, you may think that prefixing only the namespaces would get the job done. But other named elements such as global functions and traits must also be prefixed to avoid all possible error types.
To prefix PHP code, there are tools or services to execute the task:
humbug/php-scoper. Prefixes all PHP namespaces in a file/directory to isolate the code bundled in PHARs.
Interfacelab/namespacer. Namespacer allows you to rename the namespace of any composer packages. It works by adding a namespace prefix to all of the namespaces. Namespacer also prefixes the package names. It then generates a folder called "lib" that you can safely include in your WordPress plugin.
coenjacobs/mozart. Developers tool for WordPress plugins: Wraps all your projects dependencies in your own namespace. This prevents conflicts with other plugins that load the same dependencies but in different versions.
PHP-Prefixer. It's an automated online service powered by a complex rule-based system to apply prefixes to Composer dependencies. In the composer.json, you just define the prefix to apply without worrying about the nitty-gritty details.
Disclaimer: I'm the lead PHP-Prefixer developer.
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");
I make use of this library which is a more maintained version of mozart: https://github.com/BrianHenryIE/strauss
It lets you set a namespace prefix for your vendor libaries of choice and add them to a separate library which you can then autoload into you project.
It also has a lot of other useful features.
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
Related
We have developed 2 WordPress plugins which are using same composer package.
Depending on plugin versions the package included in plugin may be changed, we constantly add new functionality to our package.
The problem is that for example plugin A have version 1.0.0 of package, and plugin B have version 1.0.1, WordPress loads only one package , from plugin which loaded first, so if plugin A loaded first then plugin B will use version 1.0.0 package.
We are including autoload.php on both plugins.
Is it possible to do some configuration in WordPress or from composer side to make every plugin load and work with package included on his vendor folder ?
Is it possible to do some configuration in WordPress or from composer side to make every plugin load and work with package included on his vendor folder ?
In general no. The option about namespace rewriting has already been given by Chris Haas, so if you need to rely on different code behind the same global static names, you have to provide a different name for each version.
Another option is you align both plugins to rely on the same dependency version-stability. The example you give with 1.0.0 and 1.0.1 versions, the API should be compatible and it should not be an issue (if the package follows semantic versioning).
From the context of your question, it seems the dependency has not yet matured enough that this is an option practically.
Instead it should be possible to have the plugin which is currently based on 1.0.0 to use 1.0.1 as well. Then the version conflict is solved, as now it is the same version and can use the same names. This may not be an ideal solution, but could get you back to a working version fast and gives you more room to consider a better way in the future (e.g. having a build for those plugins that use scoping).
Additionally you could/should wrap all access to third-party libraries once in your own code so that such problems aren't that deep reaching (dependency issues tend to be harder to resolve). This methodology is independent to Wordpress or Composer, just a recommendation on how to interface to third-party dependencies (or even Wordpress itself[1], which you may know better).
If however what you ask here is already such a wrapper you build your own (e.g. in form of a composer package), consider to adhere to semantic versioning and stabilize its API first.
PHP has no built-in utility to create archives apart from PHAR, e.g. that you can have imports via names but to different code. This is likely also the reason why Composer does not support it and instead provides PSR-0/PSR-4, classmap and file inclusion autoload configuration.
As you have the scenario to share the same namespaces across the plugins - there is no other option actually as it runs in the same PHP process - the first one wins. You may however make your own plugins interoperable so that they can establish a loading order in their own hierarchy, e.g. to prefix the one autoloader before the other conditionally if it exists.
I'd probably go with scoping in the first place and only share build utilities between the plugins nowadays and have a nice package for each plugin afterwards. Yes, scoping can be PITA, but if you have this early on, you don't have to solve this later which is much harder.
Compare for the level of WordPress plugins WordPress Plugin: How do I avoid "tight coupling"? and Multiple Custom Metabox Help - both well dated so it is easier to not take code verbatim but to develop own conclusions.
When distributing Shopware Plugins as a ZIP file, it must include the vendor directory, but without the shopware/core, shopware/administration, etc. dependencies defined in the composer.json. That one I got to work.
But how to include dependencies, which themselves have dependencies, that overlap with the shopware/core dependencies?
Explicitly, I try to add a package, that depends (like Shopware itself) on psr/cache.
But when I include it, I receive the following error message, when activating the plugin:
Fatal error: Cannot declare interface Psr\Cache\CacheItemPoolInterface, because the name is already in use in /var/www/html/vendor/psr/cache/src/CacheItemPoolInterface.php on line 14
Is there any known workflow to solve these kinds of issues? The documentation, that Shopware provides, do not explain how to solve these kinds of conflicts.
If you distribute plugins for Shopware and use Composer libraries, you can find scope and namespace conflicts like Fatal error: Cannot declare interface.... The same problem is found on WordPress, Joomla, PrestaShop, or any other CMS where you don't have complete control of what is installed.
As you described, the initial problem is a conflict between the core libraries and your plugin dependencies. Additionally, you can find trouble between every package installed on the system that copies Composer packages to Shopware using the same libraries or different versions of the same libraries.
In practice, the only real and most flexible solution is prefixing the PHP code that you bundle in the ZIP file. In this way, you are entirely sure that it works independently of what is installed alongside it.
In the PHP ecosystem, there are a few solutions to prefix namespaces and customize the project scope. For instance: php-scoper, namespacer, mozart or PHP-Prefixer.
Disclaimer: I'm the lead PHP-Prefixer developer.
If it is your plugin, then there are three options.
Require the same package
Use a tool like https://github.com/humbug/php-scoper to fix the naming problems.
Install it via composer
If it is not yours, you should create an issue for the plugin provider.
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?
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.
By design, PHP and Composer assume that you develop and distribute your code in a controlled environment. However, when you publish plugins on WordPress or modules on Joomla, you distribute the code on systems where you don't have control over what other authors install. This situation can result in name collisions such as Cannot redeclare GuzzleHttp\uri_template()....
To prepare your code for multi-vendor setups, you must prefix the PHP code to avoid name collisions or version collisions (the same library with a different version is loaded first). For instance, Guzzle is a well-known and widely used library, so if you publish a plugin including it, you must prefix it before distribution.
At first glance, you may think that prefixing only the namespaces would get the job done. But other named elements such as global functions and traits must also be prefixed to avoid all possible error types.
To prefix PHP code, there are tools or services to execute the task:
humbug/php-scoper. Prefixes all PHP namespaces in a file/directory to isolate the code bundled in PHARs.
Interfacelab/namespacer. Namespacer allows you to rename the namespace of any composer packages. It works by adding a namespace prefix to all of the namespaces. Namespacer also prefixes the package names. It then generates a folder called "lib" that you can safely include in your WordPress plugin.
coenjacobs/mozart. Developers tool for WordPress plugins: Wraps all your projects dependencies in your own namespace. This prevents conflicts with other plugins that load the same dependencies but in different versions.
PHP-Prefixer. It's an automated online service powered by a complex rule-based system to apply prefixes to Composer dependencies. In the composer.json, you just define the prefix to apply without worrying about the nitty-gritty details.
Disclaimer: I'm the lead PHP-Prefixer developer.
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");
I make use of this library which is a more maintained version of mozart: https://github.com/BrianHenryIE/strauss
It lets you set a namespace prefix for your vendor libaries of choice and add them to a separate library which you can then autoload into you project.
It also has a lot of other useful features.
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
I'm making WordPress plugin that is using a few third party libraries. Is it common practice to use Composer for WordPress plugin?
If it's okay to use it, then I assume that I should provide all Composer files along with my plugin, because I don't want to make people manually run composer install.
Another question is, is it safe to use Composer's autoloading? I configured it to autoload my own classes and the libraries are of course autoloaded as well. That's convenient.
Is using Composer with WordPress plugin an overhead? Or does it have any additional issues?
This is old question, but nothing has changed since 3 years. Using Composer for requiring dependencies in WordPress plugin/themes is usually a bad idea. PHP does not allow to load more than one class with the same FQN. So if two different plugins will install the same library independently, classes from random installation of library will be loaded which may result really weird bugs (especially if these are different versions of the same library). To avoid such problems you should have only one composer.json instance per project, so in this case Composer should be run at WordPress level.
In general if you have the same package installed multiple times, you probably will get some troubles (and this will happen if every plugin maintainer will use Composer on its own). Note that this is not directly related to Composer - if you copy libraries manually you will get exactly the same problem (maybe even worse).
If you really want to use Composer in your plugin you may try tools like humbug/php-scoper which will modify namespaces of used dependencies and make them unique.
I'm encountering a wholly predictable yet incredibly annoying and tough to resolve problem.
I've been working on a PHP framework for developing WordPress plugins. It's using Composer for dependency management. Of course, the problem is if you have two instances of my framework in the same installation of WordPress, you have two vendor folders, and two copies of any packages required by the framework. Which leads to an error.
The framework functions as a separate plugin which is then inherited by any apps/plugins that are build on it.
Move the vendor folder to the core framework folder?
Problems: I don't know what would happen if I have two composer.json files and two composer.phar files writing to the same vendor folder and using the same autoloader. Presumably it wouldn't be good. Besides that, it doesn't solve the problem of collisions with composer packages that could be used by any other script or plugin outside of what I'm trying to handle.
So I'm stuck. Is this a problem that can be solved, or is it just inherent in PHP?
Composer is not really meant to be used multiple times in same project. On other hand there is nothing terribly wrong with it either, however you lose its dependencies features and need to treat this like generic case of dependencies in WordPress environment.
In other words - if you are not doing dependencies Composer way and WordPress is not doing dependencies at all, it becomes your personal problem how to deal with it.
I don't know what would happen if I have two composer.json files and two composer.phar files writing to the same vendor folder and using the same autoloader
I am not following why the vendor folder would be same if you are using multiple composer installs... Could you elaborate on how you structure it and is it meant for public or private use?
I'm not very familar with Composer or the plugin framework you are using, but in general - avoiding function/class name collisions in WordPress plugins is done in the following manner:
Assuming that your plugin (e.g. MyCoolPlugin) is written object-oriented, e.g. as a class named MyCoolPlugin, you may include the helper class/library as a subclass of MyCoolPlugin.
class_exists(), this is PHPs way of finding if a class has been defined. Assuming your helper class the following:
class MyHelperClass{
}
You may use the following check before declaring the class in each of your plugins:
if(!class_exists('MyHelperClass')){
class MyHelperClass{
}
}
Of course, there is a trade-off here, because only the first instance of the class will be used throughour WordPress. E.g. if you have two plugins with two different versions of the helper class - only one of them will be active and available at any given moment.
A global variable - e.g. define('MY_HELPER_IS_LOADED', true); in the helper files (in case you are including them via include() or require()). Then in the beginning of each included helper file check with if(defined('MY_HELPER_IS_LOADED')) return;, which will cause the currently requested file for include/require to NOT be included.
Again the tactics above are used in PHP in general, I am not sure how your plugin framework is set up exactly.