首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 相關知識

PHP 獲取文件擴展名的 N 種方法:避坑指南與最佳實踐

     編輯:PHP 相關知識

前言:看似簡單,實則暗藏陷阱

「獲取文件擴展名」是高頻需求,網上流傳著多種寫法。但實際業務中,**路徑可能包含多個點、可能無擴展名、可能以點開頭(隱藏文件)**,稍有不慎就會產生 Bug。本文對比 5 種常見方法,揭示其邊界條件差異,給出**唯一推薦的標準寫法**。

五種常見寫法對比

#代碼核心邏輯
1substr(strrchr($file, '.'), 1)找最後一個點,取其右側
2substr($file, strrpos($file, '.') + 1)找最後一點位置,截取後綴
3end(explode('.', $file))按點分割,取最後一段
4pathinfo($file)['extension']用 pathinfo 解析,取 extension 鍵
5pathinfo($file, PATHINFO_EXTENSION)pathinfo 直接返回擴展名字符串

三大殺手級測試用例

測試路徑預期結果場景說明
/home/test.d/test.txttxt路徑中含點(目錄名),文件有擴展名
/home/test.d/test'' (空串)路徑中含點,文件**無**擴展名
/home/user/file'' (空串)純文件名,無擴展名、無路徑點
.htaccess'' (空串)隱藏文件,以點開頭,無擴展名
archive.tar.gzgz多重擴展名,取最後一段

各方法在殺手用例下的表現

方法/home/test.d/test.txt/home/test.d/test/home/user/file.htaccessarchive.tar.gz致命缺陷
1. strrchrtxt ✅test ❌file ❌htaccess ❌gz ✅無擴展名時返回整個文件名/路徑尾段
2. strrpos+substrtxt ✅test ❌file ❌htaccess ❌gz ✅同方法 1,strrpos 找到目錄點
3. explode+endtxt ✅test ❌file ❌htaccess ❌gz ✅無擴展名時返回文件名;多點路徑錯誤
4. pathinfo()['extension']txt ✅Notice: Undefined index ❌Notice ❌Notice ❌gz ✅無擴展名時鍵不存在,觸發 Notice
5. pathinfo(..., PATHINFO_EXTENSION)txt ✅'' ✅'' ✅'' ✅gz ✅無缺陷,全場景正確

深度解析:為什麼只有方法 5 完美?

pathinfo() 內部實現邏輯(簡化版)


function pathinfo($path, $options = null) {
    $basename = basename($path);           // 1. 先取文件名(去除目錄)
    $pos = strrpos($basename, '.');        // 2. 在文件名中找最後一個點
    
    if ($pos === false || $pos === 0) {    // 3. 無點 或 點在首位(.htaccess)
        $extension = '';
    } else {
        $extension = substr($basename, $pos + 1);
    }
    
    $result = ['dirname' => dirname($path), 'basename' => $basename];
    if ($extension !== '') {               // 4. **只有有擴展名時才加入鍵**
        $result['extension'] = $extension;
    }
    if ($options) return $result[$options]; // 5. 直接返回指定部分(不觸發 Notice)
    return $result;
}

關鍵差異:

  • 方法 4:pathinfo($file)['extension'] 先獲取完整陣列,**無擴展名時鍵根本不存在**,直接訪問觸發 Undefined index Notice;
  • 方法 5:pathinfo($file, PATHINFO_EXTENSION) 走內部 $options 分支,**直接返回字符串(空串或擴展名)**,完全繞過陣列鍵訪問,**零 Notice、零判斷、最快**。

pathinfo 四大常量對照表

常量值含義示例返回
PATHINFO_DIRNAME1目錄路徑/home/test.d
PATHINFO_BASENAME2文件名(含擴展名)test.txt
PATHINFO_EXTENSION4擴展名(不含點)txt
PATHINFO_FILENAME8文件名(不含擴展名,PHP 5.2+)test

⚠ 注意: 這四個常量值為 1、2、4、8(位掩碼),**不能位或組合**(PATHINFO_EXTENSION | PATHINFO_FILENAME 會返回值較小的那個),每次只能查詢單一部分。

最佳實踐封裝函數


/**
 * 安全獲取文件擴展名(小寫、無點)
 * @param string $path 文件路徑或文件名
 * @return string 擴展名,無則返回空字符串
 */
function get_file_extension($path) {
    // 1. 核心:pathinfo 直接返回字符串,無 Notice、處理所有邊界
    $ext = pathinfo($path, PATHINFO_EXTENSION);
    
    // 2. 統一小寫(擴展名不區分大小寫)
    return strtolower($ext);
}

// 測試
var_dump(get_file_extension('/home/test.d/test.txt')); // string(3) "txt"
var_dump(get_file_extension('/home/test.d/test'));     // string(0) ""
var_dump(get_file_extension('.htaccess'));             // string(0) ""
var_dump(get_file_extension('archive.tar.gz'));        // string(2) "gz"

延伸:SplFileInfo 物件式用法(PHP 5.3+)


$info = new SplFileInfo('/home/test.d/test.txt');
echo $info->getExtension(); // "txt",同 pathinfo(..., PATHINFO_EXTENSION)
echo $info->getBasename('.txt'); // "test",獲取不含指定擴展名的文件名

優勢: 物件式 API、可鏈式調用、配合 Iterator 批量處理文件更優雅。

總結

  1. 唯一推薦:pathinfo($path, PATHINFO_EXTENSION) —— 標準庫、全場景正確、無 Notice、效能最優;
  2. 嚴禁使用:explode('.', $path)、strrchr、strrpos+substr、pathinfo()['extension'] —— 均在「路徑含點、無擴展名、隱藏文件」場景失效;
  3. 業務建議:封裝 get_file_extension() 統一入口,返回小寫,配合白名單驗證(in_array($ext, ['jpg','png','gif','pdf']))完成上傳校驗。

這個「小功能」折射出的工程素養:**永遠優先信任標準庫、深度理解邊界條件、封裝統一入口防止重複造輪子**。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved