如何防止WP插件之间的作曲者依赖冲突?

时间:2015-01-20 作者:Borek Bernard

在我们的插件开发中,我们使用Composer来安装。Symfony\\Process 我们以后在代码中使用的。最大的问题是how do we make sure that this dependency is not in a conflict with some other plugin 还使用Symfony\\Process 在另一个版本中。

现在我知道这主要是PHP固有的问题,但我们仍然希望为用户提供一个解决方案,至少在发生此类冲突时向他们发出警告(而不是努力失败)。例如,一种方法是扫描插件目录vendor 并尝试找出其他插件中是否使用了不兼容的版本。我知道这离完美还很远,但我只是想举个例子。

你们是怎么处理的?我知道Composer可能还不是插件开发人员的主流,但我们迟早都会遇到这个问题,所以我想知道是否有人想出了某种策略来解决这个问题。

3 个回复
SO网友:Rarst

答案是——你不能,因为WordPress不能。WP中没有依赖关系管理概念,在Composer存在之前也是这样。

自动加载(Composer或其他)的兴起对此略有帮助,因为您可能只是加载了不同的副本(希望足够接近),而不是完全致命的错误。如果你能想出一种方法来解决这个问题,你可以对此进行检查。例如,使用检查加载自的路径和定义get_included_files(), 但实际上那只是一张绷带,不是解决办法。

Composer真正帮助您的唯一方案是使用它控制整个WP安装,使用单个共享供应商文件夹。

SO网友:Hussard

在分类广告CMS上工作,深受Wordpress(osclass.org)的启发,我偶然发现了你的帖子。我们处于完全相同的情况,必须使用相同的依赖关系处理多个插件。

为了解释我们推出的解决方案,我们有两个插件:

P1在版本1.20中使用依赖项D1,P2在版本1.30中使用依赖项D1,我们必须确保加载了版本1.30才能使两个插件正常工作。

1。插件加载顺序Wordpress(和Osclass)有active_plugins 选项(英寸wp_options 表)定义了活动插件,更重要的是在我们的示例中:plugin loading order.

这是一个简单的数组。

2。版本检查在我们的两个插件开始时,我们检查D1的版本,以确保该版本是我们所需要的(或更高版本)。

// 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和D1。注:D1的加载版本为1.30

Interesting case: What happens when P1 is loaded before P2 ?

这是bump版本。

3。碰撞

记住,插件是按照中定义的顺序加载的active_plugins.

bump函数–在本例中为mdh\\u bump\\u me()–将当前插件添加到active_plugins (阵列的第一个位置)。

看起来像这样。这是与Osclass相关的代码,但可以轻松修改以与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")));
        }
    }
}
简而言之,

获取当前活动插件列表

5。自定义自动加载器(Custom Autoloader)

关于我们的自定义自动加载器(Custom Autoloader)的一句话。Composer autoloader加载每个类(即使已定义),新类替换旧类。

我们的自定义自动加载器仅在不存在的情况下加载类。加载每个类的第一个实例并忽略其他所有实例。

希望情况足够清楚。

这远不是一个理想的解决方案,但对我们来说很有效,感觉就像是向前迈出了一步。

SO网友:Moh .S

我们也遇到了同样的问题,并尝试了一种实际可行的黑客解决方案。

步骤1)查找并替换Symfony\\ProcessSymfonyMyPrefix\\Process 在项目文件夹中。

步骤2)查找并替换namespace Symfony;namespace SymfonyMyPrefix; 在项目文件夹中。

步骤3)打开autoload_files.php 由编写器创建的文件,并重命名返回数组索引,例如:

//From
return array(
    \'7b11c4dc42b3b3023073cb14e519683c\' => $vendorDir . \'/symfony/../../***.php\',
    \'8a9dc1de0ca7e01f3e08231539562f61\' => $vendorDir . \'/someotherlibifneed/../../***.php\',
);

//TO
return array(
    \'7b11c4dc42b3b3023073cb14e519683cMYPREFIX\' => $vendorDir . \'/symfony/../../***.php\',
    \'8a9dc1de0ca7e01f3e08231539562f61MYPREFIX\' => $vendorDir . \'/someotherlibifneed/../../***.php\',
);
步骤4)打开autoload_static.php 由composer创建的文件,并重命名文件数组索引,例如:

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

就是这样。。!这将有助于避免与其他WP插件发生冲突。

结束

相关推荐

Vagrantpress + composer

我在看roots.io 在博客中,我了解了Vagrant和Composer,两者的结合似乎为您提供了一个更智能的开发环境和依赖关系管理系统。我选择获取并安装Vagrantpress 因为这似乎是开始使用wordpress+vagrant最简单的方法。Vagrantpress的优点是它为您安装Wordpress及其所有依赖项。据我所知,作为Wordpress的附属品,Composer将两者结合起来的最简单方法是使用Outlandishs WordPress Packagist. 现在我的问题是,人们如何更严