PHP函数重复执行时持久保存已使用代理变量的解决方案
PHP静态方法中跨调用留存已使用代理的实现方案
问题根源
当前代码无法留存已使用代理的核心原因有两个:
$proxysused是addProxy方法内部的局部变量,每次方法执行完成后局部变量会被PHP自动回收销毁,下一次调用时会重新创建空数组,自然无法保存历史记录。- 数组追加元素时错误使用了字符串拼接符
.,$proxysused[] .= $proxies[$randIndex]属于语法写法错误,正确的数组追加写法为$arr[] = 值。
实现方案
由于addProxy是类的静态方法,直接使用类静态属性存储已使用代理列表是适配现有代码结构的最优方案,不需要修改任何外部调用逻辑:
- 在
CurlProxy类中声明私有静态属性$proxysused,静态属性的生命周期和类绑定,不会因为单次方法执行结束被销毁,可以在同一次请求的多次静态方法调用间共享数据。 - 每次选取代理前,先从全量代理列表中排除已经使用过的代理,从剩余可用代理中随机选择,避免重复。
- 选中新代理后追加到静态属性中留存记录。
- 增加兜底逻辑:如果所有代理都被使用过,自动清空已用列表重置,避免无代理可用的问题。
具体代码修改
第一步:在CurlProxy类内声明静态属性
在类的顶部位置添加属性声明:
class CurlProxy { // 新增:持久化存储已使用过的代理列表 private static $proxysused = []; // 原有其他类方法保持不变 // ... }
第二步:修改addProxy方法逻辑
static public function addProxy($handle, $r, $url) { if (!$proxies = TextHelper::commaListArray(ParserConfig::getInstance()->option('proxy_list'))) return; // 过滤已使用代理,得到可用代理列表 $availableProxies = array_diff($proxies, self::$proxysused); // 所有代理都用完时自动重置已用列表 if (empty($availableProxies)) { self::$proxysused = []; $availableProxies = $proxies; } $randIndex = array_rand($availableProxies); $proxy = $availableProxies[$randIndex]; // 记录本次使用的代理到静态属性 self::$proxysused[] = $proxy; error_log( print_r( self::$proxysused, true ) ); curl_setopt($handle, CURLOPT_PROXY, $proxy); }
可选:流程结束后重置已用列表
如果需要在单次请求的3次重试全部结束后清空已用记录,不影响后续其他请求的代理选择,可以在catch块中添加重置逻辑:
catch (\Exception $e) { if ($subida !== 3) { error_log($subida); goto newproxy; } // 重试次数耗尽,清空已用代理记录 self::$proxysused = []; $error = $e->getMessage(); $error_code = $e->getCode(); }
注:类静态属性只能在单次PHP请求生命周期内共享数据,如果需要跨多个独立请求记录已使用代理,需要将列表存储到Session、Redis或者其他持久化介质中。现有逻辑是同一次请求内重试切换代理,静态属性完全满足需求。
内容的提问来源于stack exchange,提问作者Club
相关产品推荐
相关产品推荐

