代码之家  ›  专栏  ›  技术社区  ›  Joseph Bada

Wordpress插件开发中的第三方依赖冲突

  •  6
  • Joseph Bada  · 技术社区  · 6 年前

    我正在开发一个使用composer的插件。。这意味着它在插件文件夹中有一个供应商文件夹,其中包含Guzzle HTTP依赖项

    在wordpress网站上,我们安装了这个插件,有一个现有的插件包含Guzzle HTTP

    现在,当我们激活这个插件时,我遇到了如下错误:

    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
    

    我尝试安装插件加载顺序,以强制在“我的插件”之前先加载“其他插件” 当前错误发生在其他插件的资源上。 这样,我们的自动加载将产生错误,我们可以捕捉到它。

    不幸地插件加载顺序不起作用。。

    有什么办法解决这个问题吗?

    4 回复  |  直到 6 年前
        1
  •  15
  •   rob006    6 年前

    欢迎来到WordPress地狱。我们有2018年,WordPress仍然没有任何依赖关系管理,仍然没有注意到Composer的存在。

    WordPress生态系统仅仅依赖于一个假设,即插件/主题的函数/类名称应该是唯一的。显然,将流行的第三部分编写器库与插件/主题一起分发会带来麻烦——当其他插件也这样做时,很容易发生名称冲突。没有好办法摆脱这种局面。

    如果您想要一个独立插件的防弹解决方案,您应该在您的 vendor 例如,带有插件前缀的目录 myplygin\vendor 然后 GuzzleHttp\Client 成为 myplugin\vendors\GuzzleHttp\Client ,因此没有名称冲突的风险。这将需要一些工作来为此编写脚本(或者您可以使用一些现有的解决方案,如 humbug/php-scoper ),并且您可能会得到许多重复的依赖项(10个插件可能会带来10次相同的库,但名称空间不同),但这是将现代工具和模式集成到过时软件中的成本。

    如果您正在为自己编写此插件,并控制最终安装,您可以尝试 use Composer for installing WordPress and its plugins 。如果第三方插件捆绑了一些composer库,您可能仍然需要修复它们(通过forking),但从长远来看,这将简化许多事情,并且您可以避免为每个插件复制库。

        2
  •  4
  •   Anibal Sanchez    3 年前

    根据设计, PHP 创作者 假设您在受控环境中开发和分发代码。但是,当您在上发布插件时 WordPress 或上的模块 逐浪 ,您可以在无法控制其他作者安装的系统上分发代码。这种情况可能导致 名称冲突 例如 Cannot redeclare GuzzleHttp\uri_template()...

    要为多供应商设置准备代码,必须 为PHP代码添加前缀 避免名称冲突或版本冲突(首先加载具有不同版本的相同库)。例如,Guzzle是一个众所周知且使用广泛的库,因此如果发布包含它的插件,则必须在发布之前为其添加前缀。

    乍一看,您可能认为只在名称空间前面加前缀就能完成工作。但其他命名元素(如全局函数和特性)也必须加前缀,以避免所有可能的错误类型。

    要为PHP代码添加前缀,可以使用以下工具或服务来执行任务:

    • humbug/php-scoper 。在文件/目录中为所有PHP名称空间添加前缀,以隔离PHARs中捆绑的代码。
    • Interfacelab/namespacer .Namespacer允许您重命名任何composer包的命名空间。它通过向所有名称空间添加名称空间前缀来工作。Namespacer还为包名称加前缀。然后生成一个名为“lib”的文件夹,您可以将其安全地包含在WordPress插件中。
    • coenjacobs/mozart .WordPress插件开发工具:将所有项目依赖项包装在您自己的命名空间中。这可以防止与加载相同依赖项但版本不同的其他插件发生冲突。
    • PHP-Prefixer 。这是一个自动化的在线服务,由一个复杂的基于规则的系统提供支持,可以将前缀应用于Composer依赖项。在 composer.json ,您只需定义要应用的前缀,而不必担心细节。

    免责声明:我是PHP前缀器的首席开发人员。

        3
  •  1
  •   Ji't    6 年前

    不建议这样做,但如果必须使用它

    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");
    
        4
  •  -1
  •   Ji't    6 年前

    我猜GuzzleHttp/functions中有一个函数。第31行的php,因此您可以使用类似的内容:

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

    或者可以使用is\u plugin\u active函数检查插件是否已安装。在这种情况下,可以忽略包含文件

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