PHP DOMDocument替换图片URL遇双点空格触发Invalid '..'-range报错
报错信息
Invalid '..'-range, '..'-range needs to be incrementing
问题描述
我此前在西班牙语论坛提出过相同问题,但未得到有效解答,找不到其他解决方案因此在此提问。
我的需求是批量修改多篇文章条目中的部分图片URL:对于图片URL路径规则简单的条目,修改逻辑可正常运行;但URL路径中夹杂空格、连续双点的条目会触发上述报错。
我从数据库读取数据开展测试,选取了触发该报错的ID=2的用户数据作为测试样本,以下是我用于修改图片URL的测试代码:
$data= User::find(2); $html = $data->name; $html = "<body>$html</body>"; $dom = new DOMDocument; $dom->loadHTML($html, LIBXML_COMPACT | LIBXML_HTML_NOIMPLIED | LIBXML_NONET | LIBXML_HTML_NODEFDTD); if (is_null($dom)) { } else { $a_nodelist = $dom->getElementsByTagName('p'); foreach ($a_nodelist as $enlace) { $img = $enlace->getElementsByTagName('img')->item(0); if ($img) { $urlImagen = $img->getAttribute('src'); $imagenArreglo = explode("/", $urlImagen); $nombreImagen = end($imagenArreglo); $rutasinImagen = rtrim($urlImagen, $nombreImagen); dd($rutasinImagen); $nuevaruta = 'http://www.rumberos.net/wp-content/uploads/2022/imagen/'; $file = fopen("archivo.txt", "a"); fwrite($file, $data->id . PHP_EOL); fclose($file); DB::table("users") ->where("id", "=", $data->id) ->update(["name" => DB::raw("REPLACE(name, '$rutasinImagen', '$nuevaruta')")]); }
文章内容以HTML格式存储,因此我使用DOMDocument解析DOM结构提取图片URL,该逻辑在部分URL规范的文章上可正常运行,我推测问题出在格式不规范的URL上。触发报错的测试条目中的图片URL如下:
http://midominio.com/images/2014/HTV- Premios Heat - Juanes..jpg
我在拆分字符串提取图片文件名的步骤添加了dd调试打印,该步骤运行正常,但在执行rtrim移除URL中文件名部分、后续数据库替换操作时触发报错,我怀疑异常是URL中包含的连续双点、空格特殊字符导致的。
故障原因
报错根源是对rtrim函数的用法理解错误:
rtrim的第二个参数是字符掩码集合,不是要完整删除的后缀字符串。函数会从字符串末尾开始,逐个检查字符是否在掩码集合内,只要命中就删除,直到碰到不在集合内的字符为止。- 传入的文件名参数是
HTV- Premios Heat - Juanes..jpg,其中包含.字符,当函数处理到URL末尾的连续..时,会尝试将..解析为字符范围(类似a..z代表a到z的所有字符),但单独的..无法构成合法的递增字符范围,就会抛出对应错误。 - 额外隐患:直接把URL变量拼接进SQL语句,URL里的空格、单引号等特殊字符不仅会导致SQL语法错误,还存在SQL注入风险。
修复方法
- 弃用
rtrim处理URL路径,改用字符串拆分的方式准确提取目录路径,替换原有rtrim相关逻辑:$imagenArreglo = explode("/", $urlImagen); $nombreImagen = array_pop($imagenArreglo); // 弹出数组最后一个元素,即文件名 $rutasinImagen = implode("/", $imagenArreglo) . "/"; // 拼接剩余部分为目录路径,末尾补斜杠 - 改写数据库更新逻辑,用参数绑定的方式传入替换值,避免特殊字符导致的语法问题和安全风险:
DB::table("users") ->where("id", $data->id) ->update([ "name" => DB::raw("REPLACE(name, :old_path, :new_path)") ]) ->setBindings([ 'old_path' => $rutasinImagen, 'new_path' => $nuevaruta ]); - 可选优化:处理URL前先做一次URL解码,避免编码后的空格(
%20)、特殊字符导致路径匹配失败。
内容的提问来源于stack exchange,提问作者Isaac Lovera
相关产品推荐
相关产品推荐

