MyPluginOne与MyPluginTwo谷歌登录命名空间冲突问题解决咨询
我有两个WordPress插件MyPluginOne和MyPluginTwo,配置MyPluginTwo的谷歌社交登录(Login as Google)时触发致命错误:
Fatal error: Uncaught Error: Google\Auth\HttpHandler\HttpHandlerFactory::build(): Argument #1 ($client) must be of type ?GuzzleHttp\ClientInterface, MyPluginOne\GuzzleHttp\Client given, called in C:\Users\WPB\Local Sites\MyPluginOne-google-login\app\public\wp-content\plugins\wp-MyPluginOne\lib\Google-GA4\vendor\google\apiclient\src\Client.php on line 220 in C:\Users\WPB\Local Sites\MyPluginOne-google-login\app\public\wp-content\plugins\MyPluginTwo-pro\addons\social-login\sdk\google-client\vendor\google\auth\src\HttpHandler\HttpHandlerFactory.php on line 34
我尝试把MyPluginOne\GuzzleHttp\Client修改为GuzzleHttp\Client,但出现类已声明的冲突问题。MyPluginOne是通过php-scoper添加命名空间的,其scoper.inc.php配置如下:
<?php declare (strict_types=1); namespace MyPluginOne; // scoper.inc.php use MyPluginOne\Isolated\Symfony\Component\Finder\Finder; return [ 'prefix' => 'MyPluginOne', // string|null 'output-dir' => null, // string|null 'finders' => [], // list<Finder> 'patchers' => [], // list<callable(string $filePath, string $prefix, string $contents): string> 'exclude-files' => [], // list<string> 'exclude-namespaces' => ['Google\\', 'Grpc\\', 'Composer\\'], // list<string|regex> 'exclude-constants' => [], // list<string|regex> 'exclude-classes' => [], // list<string|regex> 'exclude-functions' => [], // list<string|regex> 'expose-global-constants' => \true, // bool 'expose-global-classes' => \true, // bool 'expose-global-functions' => \true, // bool 'expose-namespaces' => [], // list<string|regex> 'expose-constants' => [], // list<string|regex> 'expose-classes' => [], // list<string|regex> 'expose-functions' => [], ];
我需要解决:
- 应该在哪个插件中修复该命名空间冲突?
- 如何在MyPluginOne内部完成修复?
- 给MyPluginTwo添加命名空间会导致其自身功能故障,卸载MyPluginOne后谷歌登录恢复正常,但必须同时使用两个插件。
1. 修复插件选择
必须在MyPluginOne中修复,冲突根源是它通过php-scoper隔离依赖时,未正确处理GuzzleHttp与Google客户端的交互逻辑,导致隔离后的Guzzle实例被MyPluginTwo的Google代码错误调用;而MyPluginTwo无法通过添加命名空间修复(会引发自身功能故障)。
2. MyPluginOne内部修复方案
方案一:调整php-scoper配置,同步隔离Google与Guzzle命名空间
修改scoper.inc.php中的exclude-namespaces,移除Google\\,让php-scoper给Google相关代码也加上MyPluginOne前缀,确保Google客户端使用隔离后的MyPluginOne\GuzzleHttp\Client,避免与MyPluginTwo的全局Guzzle冲突:
'exclude-namespaces' => ['Grpc\\', 'Composer\\'],
修改完成后,重新用php-scoper编译MyPluginOne,确保所有Google和Guzzle的代码都被正确添加前缀。
方案二:添加自定义patcher,强制Google代码适配隔离后的Guzzle
若不想隔离Google命名空间,可在scoper.inc.php的patchers数组中添加自定义补丁,替换Google代码中的Guzzle引用为隔离后的命名空间:
'patchers' => [ function (string $filePath, string $prefix, string $contents): string { // 匹配Google客户端核心文件 if (str_contains($filePath, 'google/apiclient/src/Client.php') || str_contains($filePath, 'google/auth/src/HttpHandler/HttpHandlerFactory.php')) { return str_replace( 'GuzzleHttp\ClientInterface', $prefix . '\GuzzleHttp\ClientInterface', $contents ); } return $contents; }, ],
该补丁会自动将Google代码中的全局GuzzleHttp\ClientInterface替换为MyPluginOne\GuzzleHttp\ClientInterface,解决类型不匹配错误。
方案三:禁用Guzzle的全局暴露
修改scoper.inc.php中的expose-global-classes为false,同时确保expose-namespaces不包含GuzzleHttp\\:
'expose-global-classes' => \false,
此方法会让MyPluginOne的Guzzle仅在隔离命名空间内可用,MyPluginTwo的Google登录会使用自身的Guzzle实例,避免冲突。注意:需确保MyPluginOne内部所有依赖Guzzle的代码都使用隔离后的命名空间,否则会引发自身功能故障。
3. 验证修复
编译MyPluginOne后,重新安装并激活两个插件,测试MyPluginTwo的谷歌登录功能,确认错误消失且两个插件功能正常。
内容的提问来源于stack exchange,提问作者ahmedwp

