pathinfo($filename, pathinfo_extension)最稳,因其基于内核路径语义解析,天然区分目录分隔符与点号,准确返回最后一段扩展名(如a.tar.gz→gz),且对无扩展名(readme)、隐藏文件(.htaccess)、空字符串均安全返回空,不触发警告;而substr+strrchr或explode等字符串方法在边界场景易出错、误判或报错。

在PHP中验证上传文件类型、按扩展名路由静态资源、生成安全的存储文件名时,必须准确提取后缀名;用错方法会导致.gitignore被当成ini处理、archive.tar.gz被误判为gz而跳过tar层校验、甚至对README这类无点文件触发PHP警告。
pathinfo($filename, PATHINFO_EXTENSION) 为什么最稳
这一步操作起来很简单,直接传入文件路径和常量即可:$ext = pathinfo($filename, PATHINFO_EXTENSION);
它专为提取扩展名设计,底层不依赖字符串查找或正则匹配,而是基于PHP内核对路径结构的语义解析。这意味着它天然能区分路径分隔符(/ 和 \)与扩展名分隔符(.),不会把 /var/log/apache2.4/error.log 中的 2.4 当作扩展名。
【必须显式传入 PATHINFO_EXTENSION 参数】 如果只写 pathinfo($filename),返回的是完整数组,后续直接 echo $info['extension'] 在无扩展名文件(如 .htaccess)上会触发 Notice: Undefined index: extension。
其他方法为什么容易翻车
方法一:用 substr(strrchr($filename, '.'), 1)
这行代码看着短,但会在三类场景彻底失效:文件名以点开头却无扩展名(如 .gitignore),strrchr 返回整个字符串,substr 就截出 gitignore;文件名不含点(如 README),strrchr 返回 false,substr(false, 1) 触发警告并返回空;路径含多个点但非扩展名(如 config.ini.bak),它只取最后一个点后内容,看似得到 bak,实则掩盖了逻辑缺陷——你根本没判断这个点是否属于文件名部分。
方法二:用 explode('.', $filename) 取最后一段
遇到 image.jpeg 没问题,但面对 archive.tar.gz 就只能拿到 gz,而 tar 层信息完全丢失;更危险的是,如果文件名是 .env.local.php,explode 会拆出空字符串作为第一段,最后一段却是 php,导致隐藏文件被错误放行。
边界情况实测对比
第一步:准备测试样本 —— ['', '.htaccess', 'README', 'a.tar.gz', '/home/user/file.txt', 'config.ini.bak']
第二步:对每个样本分别运行 pathinfo($f, PATHINFO_EXTENSION) 和 substr(strrchr($f, '.'), 1)
第三步:观察输出差异 —— pathinfo 对空字符串返回空、对 .htaccess 返回空、对 a.tar.gz 返回 gz;而 substr+strrchr 对空字符串触发警告、对 .htaccess 返回 htaccess、对 README 返回空但伴随 Warning: strrchr(): Empty delimiter。
第四步:确认需求是否真要多级扩展名 —— 若需 tar.gz,不能靠多次调用 pathinfo 套娃,因为 pathinfo('a.tar.gz', PATHINFO_FILENAME) 返回 a.tar,再对其调用仍得 tar,无法还原原始后缀组合。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











