admin管理员组文章数量:1287136
In our plugin development we use Composer to install e.g. Symfony\Process
that we later use in the code. The big question is how do we make sure that this dependency is not in a conflict with some other plugin also using Symfony\Process
in another version.
Now I know this is mostly an inherent PHP issue but still, we'd like to offer our users a solution that at least warns them when such conflict happens (instead of failing hard). One approach, for example, would be to scan the plugins directory for vendor
folders and try to figure out whether an incompatible versions are used in some other plugin. I know this far (like really, really far) from perfect but I'm just trying to give an example.
How do you guys deal with this? I know Composer is probably not mainstream amongst plugin developers yet but we all will have this problem sooner or later so I'm wondering if anyone has figured out some sort of strategy for it.
In our plugin development we use Composer to install e.g. Symfony\Process
that we later use in the code. The big question is how do we make sure that this dependency is not in a conflict with some other plugin also using Symfony\Process
in another version.
Now I know this is mostly an inherent PHP issue but still, we'd like to offer our users a solution that at least warns them when such conflict happens (instead of failing hard). One approach, for example, would be to scan the plugins directory for vendor
folders and try to figure out whether an incompatible versions are used in some other plugin. I know this far (like really, really far) from perfect but I'm just trying to give an example.
How do you guys deal with this? I know Composer is probably not mainstream amongst plugin developers yet but we all will have this problem sooner or later so I'm wondering if anyone has figured out some sort of strategy for it.
Share Improve this question asked Jan 20, 2015 at 12:27 Borek BernardBorek Bernard 1,4783 gold badges17 silver badges29 bronze badges3 Answers
Reset to default 8The answer is — you can't because WordPress can't. There is no dependency management concept in WP and it was the same case before Composer had even existed.
The rise of autoload (Composer or otherwise) slightly helps with it, since you might just be getting different copy loaded (hopefully close enough) rather than outright fatal error. You can check for this, if you devise a method to. For example checking the paths the definitions where loaded from with get_included_files()
, but really that's just a bandaid not a solution.
The only scenario in which Composer really helps you with it is using it to control whole WP installation, with single shared vendor folder.
Working on a classifieds CMS, heavily inspired by Wordpress (osclass not to name it), I stumbled upon your thread. We are in the exact same situation, having to deal with multiple plugins using the same dependency.
To explain the solution we've pulled out, let's we've got two plugins :
- P1 uses dependency D1 in version 1.20
- P2 uses dependency D1 in version 1.30
We have to make sure that version 1.30 is loaded for both plugins to work properly.
1. Plugins loading order
Wordpress (and Osclass) have a active_plugins
option (in wp_options
table) that defines active plugins and more importantly in our case : plugin loading order.
This is a simple array.
2. Version check
At the start of our two plugins, we check the version of D1 to be sure that the version is what we need (or superior).
// Custom autoloader, we'll check it in a moment.
require __DIR__ . "/vendor/composer_components/madhouse/autoloader/autoload.php";
if(!function_exists("mdh_utils") || (function_exists("mdh_utils") && strnatcmp(mdh_utils(), "1.30") === -1)) {
// Dependency version is lower than 1.30 (which we need), let's bump.
mdh_bump_me();
} else {
// Rest of the plugin code.
}
Simple case: what happens when P2 is loaded before P1 ?
- P2 is loaded and D1 with it. Note: loaded version of D1 is 1.30.
- P1 is loaded next, checks if D1 is loaded and version is 1.20 or higher and find the version 1.30 then loads normally.
Everything's good.
Interesting case: What happens when P1 is loaded before P2 ?
- P1 is loaded before P2, our dependency and our plugin P1 are loaded normally. Note: loaded version of D1 is 1.20.
- P2 is loaded next, it checks D1 version and find out that D1 has been loaded but version is not high enough (1.20 instead of the required 1.30).
Here comes the bump version.
3. Bump !
Remember, plugins are loaded in the order defined in active_plugins
.
The bump function – in this case mdh_bump_me() – will bump the current plugin to the top of the active_plugins
(first position of the array).
Looks like this. This is Osclass-related code but it can easily be modified to work with Wordpress :
function mdh_bump_me()
{
// Sanitize & get the {PLUGIN_NAME}/index.php.
$path = str_replace(osc_plugins_path(), '', osc_plugin_path(__FILE__));
if(osc_plugin_is_installed($path)) {
// Get the active plugins.
$plugins_list = unserialize(osc_active_plugins()); // This is the active_plugins fields unserialized.
if(!is_array($plugins_list)) {
return false;
}
// Remove $path from the active plugins list
foreach($plugins_list as $k => $v) {
if($v == $path) {
unset($plugins_list[$k]);
}
}
// Re-add the $path at the beginning of the active plugins.
array_unshift($plugins_list, $path);
// Serialize the new active_plugins list.
osc_set_preference('active_plugins', serialize($plugins_list));
if(Params::getParam("page") === "plugins" && Params::getParam("action") === "enable" && Params::getParam("plugin") === $path) {
//osc_redirect_to(osc_admin_base_url(true) . "?page=plugins");
} else {
osc_redirect_to(osc_admin_base_url(true) . "?" . http_build_query(Params::getParamsAsArray("get")));
}
}
}
In a nutshell,
- Get current active_plugins list.
- Remove the current plugin from it.
- Add the current plugin at the beginning of the array.
- Save the option to the database.
- Redirect to the same page.
5. Custom Autoloader
A word on our custom autoloader. Composer autoloader loads every class (even if it has been already defined), the new replacing the old one.
Our custom autoloader only loads a class if does not exist yet. Loads the first instance of each class and ignore every other ones.
Hope it's clear enough.
Far-far-far from an ideal solution but works for us and it feels like a step forward.
We have faced the same issue, and tried a hackish solution which actually worked.
Step 1) Find and replace all the occurances of Symfony\Process to SymfonyMyPrefix\Process within your project folder.
Step 2) Find and replace all the occurances of namespace Symfony; to namespace SymfonyMyPrefix; within your project folder.
Step 3) Open the autoload_files.php file created by the composer and rename the return array indexes, example:
//From
return array(
'7b11c4dc42b3b3023073cb14e519683c' => $vendorDir . '/symfony/../../***.php',
'8a9dc1de0ca7e01f3e08231539562f61' => $vendorDir . '/someotherlibifneed/../../***.php',
);
//TO
return array(
'7b11c4dc42b3b3023073cb14e519683cMYPREFIX' => $vendorDir . '/symfony/../../***.php',
'8a9dc1de0ca7e01f3e08231539562f61MYPREFIX' => $vendorDir . '/someotherlibifneed/../../***.php',
);
Step 4) Open the autoload_static.php file created by the composer and rename the files array indexes, example:
//From
return array(
'7b11c4dc42b3b3023073cb14e519683c' => $vendorDir . '/symfony/../../***.php',
'8a9dc1de0ca7e01f3e08231539562f61' => $vendorDir . '/someotherlibifneed/../../***.php',
);
//TO
return array(
'7b11c4dc42b3b3023073cb14e519683cMYPREFIX' => $vendorDir . '/symfony/../../***.php',
'8a9dc1de0ca7e01f3e08231539562f61MYPREFIX' => $vendorDir . '/someotherlibifneed/../../***.php',
);
Note: Make sure that array indexes are the same as that of the array indexes on step 3.
Thats it..! This should help avoiding conflicts with other WP plugins.
本文标签: How to prevent Composer dependency conflicts amongst WP plugins
版权声明:本文标题:How to prevent Composer dependency conflicts amongst WP plugins? 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1741306910a2371421.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论