WordPress plugin + Composer? - php

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.

Related

Same composer package in 2 different WordPress plugins

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.

How to include overlapping composer dependencies in a Shopware 6 plugin ZIP?

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.

Use the same part of code in multiple WP plugins [duplicate]

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

3rd party dependency conflict in developing Wordpress Plugin

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

How to choose the right Composer packages?

I'm a bit confused about using Composer.
I have built my own package manager, that uses a config-file and a large SVN-repo that contains all possible libraries (both PHP and Javascript / CSS) I need in several different projects. I download these packages myself from the library websites.
Now I'm trying to use Composer instead, since I like the automatic dependency checking and want to use something that everybody else does. But how do you decide what packages are best?
For example, for CodeMirror, I used to download the latest stable version from https://codemirror.net/ . But when I look in Packagist I see so many different versions that I don't know which to choose. It seems everybody can create new packages for Composer ? I just need the official ones.
So, how do you guys pick the packages you need?
To answer your question directly, for any component you want to import into your project, the way to find the "canonical" source - as opposed to various forks - is to go back to the original source and see what their usage/install instructions suggest. If they support a Packagist-based install, they will usually say so. If not, but there is a composer.json in their (typically) Github repository, then you can add the repository to your composer.json and then require the package as normal.
However, more generally, I think there is some confusion about what Composer really does. As noted in the comments, Composer is a dependency manager for PHP. Packagist is the primary repository for composer-managed packages. The CodeMirror library you cited is fundamentally a javascript library.
Now it's true that if you search for "codemirror" on Packagist, you will see lots of results there, some of which are labeled as Javascript components. But they are primarily:
wrappers that allow consumers to interact with or simply load CodeMirror in PHP-based view-scripts, like conquer/codemirror for the Yii framework, or nitrado/code-mirror-bundle for the Symfony framework; or
shim repositories for the Components project - like components/jquery, for example - which are then installed using the command-line script from their Component Installer for Composer
Bottom line: Composer is primarily used for importing PHP packages. It takes some gymnastics - like the Component Installer for Composer noted above - to make it usable/helpful for non-PHP packages.

Categories