PHP出现extract() expects parameter 1 to be array警告致CPU升高问题
问题根因分析
- 直接触发警告的原因:
extract(parse_url($base));这行代码没有校验parse_url($base)的返回值。当传入的$base不是合法URL时,parse_url会返回false而非数组,传给extract就会抛出你看到的PHP警告。 - 服务器过载、CPU升高的原因:
- 大量调用这个函数时产生的PHP警告会持续写入错误日志,频繁IO消耗资源
- 后续逻辑依赖
parse_url解析出的$scheme、$host等变量,解析失败后这些变量未定义,会额外抛出Undefined variable系列警告,进一步加重日志写入负担 - 代码末尾的
preg_replace循环,当$abs变量因前面解析失败产生异常格式的字符串时,可能出现替换逻辑无法收敛的情况,导致循环长时间运行占用CPU
修复方案
核心修改点
- 先校验
parse_url返回值,合法再继续执行,不合法直接返回fallback值 - 取消
extract调用,直接操作解析后的数组,避免变量污染和未定义问题 - 优化路径清理逻辑,增加最大执行次数限制,避免潜在死循环
修复后完整代码:
<?php function rel2abs($rel, $base) { if (empty($rel)) $rel = "."; if (parse_url($rel, PHP_URL_SCHEME) != "" || strpos($rel, "//") === 0) return $rel; if ($rel[0] == "#" || $rel[0] == "?") return $base.$rel; // 新增base合法性校验 $baseParts = parse_url($base); if (!$baseParts || !isset($baseParts['scheme'], $baseParts['host'])) { // 可根据业务需求调整不合法场景的返回值 return $rel; } $scheme = $baseParts['scheme']; $host = $baseParts['host']; $path = isset($baseParts['path']) ? preg_replace('#/[^/]*$#', "", $baseParts['path']) : "/"; $port = isset($baseParts['port']) && $baseParts['port'] != 80 ? ":" . $baseParts['port'] : ""; $auth = ""; if (isset($baseParts['user'])) { $auth = $baseParts['user']; if (isset($baseParts['pass'])) { $auth .= ":" . $baseParts['pass']; } $auth .= "@"; } if ($rel[0] == '/') $path = ""; $abs = "$auth$host$path$port/$rel"; // 优化路径清理逻辑,最多执行5次防止死循环 $maxCleanTimes = 5; while($maxCleanTimes > 0) { $newAbs = preg_replace(['#(/\.?/)#', '#/(?!\.\.)[^/]+/\.\./#'], '/', $abs); if ($newAbs == $abs) break; $abs = $newAbs; $maxCleanTimes--; } return $scheme . "://" . $abs; }
内容的提问来源于stack exchange,提问作者Dinesh chandra
相关产品推荐
相关产品推荐

