str_replace() 适合简单替换,但易误改 data-src 等属性;推荐用 preg_replace() 限定 src/href 属性内替换,多文件用 glob() 批量处理,复杂场景(如 srcset、内联 css)须用 domdocument 解析。

用 str_replace() 替换 HTML 文件里的 src 和 href 路径最直接
PHP 处理单个文件路径替换,str_replace() 是最快、最可控的选择。它不依赖正则,不会误匹配 URL 参数或注释内容,适合批量更新静态资源路径(比如把 /images/ 换成 /static/images/)。
常见错误是直接对整个 HTML 字符串无差别替换,结果把 data-src、srcset 甚至 JSON 字符串里的路径也改了。必须限定在属性范围内操作。
- 先用
file_get_contents()读取文件,别用readfile()—— 后者不能修改后写回 - 只替换
src="..."和href="..."中的路径,推荐用preg_replace()配合边界锚点,例如:$html = preg_replace('/(src|href)="([^"]*)\/images\//', '$1="/static/images/', $html); - 如果路径含变量或版本号(如
/images/logo.png?v=1.2),正则里要允许[^"]*匹配任意非引号字符,否则会截断
处理多个文件时,用 glob() + file_put_contents() 自动遍历
批量更新几十个 HTML 或 PHP 模板文件,手动逐个打开太慢。用 glob() 找出目标文件列表,再循环处理,是最轻量的方案。
注意 Windows 和 Linux 下路径分隔符差异:PHP 的 glob() 在 Windows 下识别 \,但代码里统一用 / 更安全,PHP 会自动转换。
立即学习“PHP免费学习笔记(深入)”;
- 匹配所有模板:
glob('templates/**/*.php')(需 PHP 5.3+,开启GLOB_BRACE可扩展匹配) - 避免覆盖原文件:先用
file_get_contents()读,处理完再用file_put_contents($file, $new_content)写回 - 加个判断防止空内容被写入:
if (strlen($new_content) > 0) { file_put_contents(...); } - 写入失败时
file_put_contents()返回false,建议检查并trigger_error()提示具体哪个文件出错
遇到 srcset、data-src 或 CSS 内联路径怎么办
srcset 是响应式图片的关键属性,格式复杂(含逗号、空格、w/dpr 描述符),str_replace() 会破坏结构;data-src 则常用于懒加载,同样需要单独处理。
此时不能再靠简单字符串替换,得用 DOM 解析器。PHP 自带的 DOMDocument 能准确定位元素和属性,但要注意它会自动修正 HTML 结构(比如补全 标签),可能影响原始格式。
- 加载时禁用自动修复:
$dom = new DOMDocument();<br>$dom->loadHTML($html, LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD);
- 遍历所有
img、link、script元素:$imgs = $dom->getElementsByTagName('img');,再检查是否有src、srcset、data-src -
srcset值需按逗号分割,对每个 URL 片段单独替换,再拼回(保留原有空格和描述符) - CSS 内联样式中的
url(...)要额外用正则提取,因为DOMDocument不解析 style 属性值内部
写入文件前务必校验路径合法性,防止 ../ 被误替换引发越权
批量替换时若没限制范围,可能把 ../../admin/config.php 里的 /admin/ 也替换成新路径,导致跳转到错误目录,甚至暴露敏感路径。
更危险的是,如果替换逻辑写成 str_replace('/images/', '/cdn/images/', $path),而原始路径是 /user/images/avatar.jpg,就会变成 /user/cdn/images/avatar.jpg —— 明显错误。
- 替换前用
parse_url()判断是否为绝对路径:if (parse_url($url, PHP_URL_SCHEME) === null),只处理相对路径 - 用
preg_match()确保只匹配以/images/开头的路径(加^\/images\/锚点),避免中段匹配 - 对用户上传的 HTML 文件,先
strip_tags()或白名单过滤,防止注入恶意 JS 路径干扰替换逻辑 - 执行前加 dry-run 模式:用
echo "$file → ".substr($new_content, 0, 100)."...";快速确认效果,别一上来就全量覆盖
路径替换看着简单,真正稳定运行要同时扛住 HTML 结构变异、路径语义混淆、跨平台路径处理三重干扰。DOM 解析虽重,但面对 srcset 和内联样式时几乎没有替代方案。











