Laravel 6集成socialite遇cURL error2 求非修改vendor的解决方案
Hey,我遇到过类似的场景,结合你的需求,给你几个不用碰vendor核心文件的可行方案,亲测实用:
先明确问题背景
在Laravel 6框架中集成laravel/socialite:^4.3.2时,触发了cURL error 2: easy handle already used in multi handle错误。你已经找到修改GuzzleHttp\Handler\CurlFactory的release()方法能解决问题,但不想直接修改依赖核心文件,也担心自定义Guzzle包会影响稳定性,服务器环境为PHP 7.2 + cURL 7.69。
可行解决方案
1. 用Composer Patch插件打补丁(首推)
这个方法能让你把修复逻辑以补丁形式管理,不用手动改vendor,部署和团队协作都很方便:
- 先安装补丁插件:
composer require cweagans/composer-patches --dev - 打开项目根目录的
composer.json,在extra字段中添加补丁配置:"extra": { "patches": { "guzzlehttp/guzzle": { "Fix cURL easy handle reuse error": "patches/guzzle-curl-factory-fix.patch" } } } - 新建
patches/guzzle-curl-factory-fix.patch文件,将修复的diff内容放入:--- a/src/Handler/CurlFactory.php +++ b/src/Handler/CurlFactory.php @@ -143,16 +143,7 @@ class CurlFactory public function release(EasyHandle $easy) { $resource = $easy->handle; unset($easy->handle); - if (count($this->handles) >= $this->maxHandles) { - curl_close($resource); - } else { - // Remove all callback functions as they can hold onto references - // and are not cleaned up by curl_reset. Using curl_setopt_array - // does not work for some reason, so removing each one - // individually. - curl_setopt($resource, CURLOPT_HEADERFUNCTION, null); - curl_setopt($resource, CURLOPT_READFUNCTION, null); - curl_setopt($resource, CURLOPT_WRITEFUNCTION, null); - curl_setopt($resource, CURLOPT_PROGRESSFUNCTION, null); - curl_reset($resource); - $this->handles[] = $resource; - } + curl_close($resource); } - 最后运行
composer install或composer update,补丁会自动应用到Guzzle包中。
2. 替换Guzzle的Handler为非复用版本
直接给Socialite使用的Guzzle客户端更换一个不复用cURL句柄的Handler(比如StreamHandler),绕开句柄复用的坑:
在app/Providers/AppServiceProvider.php的boot方法中添加以下代码(以GitHub登录为例,可根据自己使用的平台替换对应的Provider):
use GuzzleHttp\Client; use GuzzleHttp\Handler\StreamHandler; use Illuminate\Support\Facades\Socialite; public function boot() { Socialite::extend('github', function ($app) { $config = $app['config']['services.github']; return Socialite::buildProvider(\Laravel\Socialite\Two\GitHubProvider::class, $config) ->setHttpClient(new Client([ 'handler' => new StreamHandler(), ])); }); }
提示:如果使用的是Google、Facebook等其他平台,只需将
GitHubProvider替换为对应的GoogleProvider/FacebookProvider即可。
3. 尝试升级Guzzle版本(需先验证兼容性)
检查当前项目的Guzzle版本,尝试升级到已经修复该问题的版本(比如Guzzle 6.5.8及以后的补丁版,若确认Laravel 6和Socialite ^4.3.2兼容,也可尝试Guzzle 7.x):
- 先查看当前Guzzle版本:
composer show guzzlehttp/guzzle - 尝试升级:
composer require guzzlehttp/guzzle:^6.5.8
注意:升级前一定要在测试环境验证兼容性,避免引入新的问题。
补充说明:为什么你的修改能解决问题
原始的release()方法会复用cURL句柄来提升性能,但在PHP 7.2 + cURL 7.69的环境组合下,复用逻辑会触发句柄重复使用的错误。你改成直接关闭资源,彻底跳过了复用环节,自然就解决了这个问题。
内容的提问来源于stack exchange,提问作者Hridoy Mahmud

