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

PHP opendir() 實戰:開啟目錄控制代碼、錯誤處理、FTP 封裝協定支援、遞迴掃描基礎

     編輯:PHP 綜合知識

opendir() 是 PHP 目錄操作的**入口函數**,回傳**目錄控制代碼 (resource)** 供 readdir()、rewinddir()、closedir() 使用。本文詳細說明語法、參數、回傳值、錯誤處理、FTP/HTTP 封裝協定支援、資源釋放最佳實務,並提供遞迴掃描基礎範例。

一、語法與參數

opendir(string $path, ?resource $context = null): resource|false
  • $path:目錄路徑,支援本地路徑、ftp://、https://、ssh2.sftp:// 等封裝協定 (需對應擴充套件)。
  • $context:串流上下文 (如 FTP 認證、HTTP Header、SSL 驗證)。
  • 成功回傳 resource (目錄控制代碼),失敗回傳 false 並觸發 E_WARNING。

二、基礎掃描範例 (含錯誤處理)

<?php
$dir = './';
$handle = @opendir($dir);
if ($handle === false) {
    die("無法開啟目錄: $dir (權限不足或不存在)");
}

echo "<ul>";
while (($entry = readdir($handle)) !== false) {
    // 過濾 . 和 ..
    if ($entry === '.' || $entry === '..') continue;
    echo "<li>$entry</li>";
}
echo "</ul>";

closedir($handle); // 必須釋放資源

三、FTP 遠端目錄掃描

$ftpPath = 'ftp://user:pass@ftp.example.com/public_html/';
$ctx = stream_context_create([
    'ftp' => ['overwrite' => true, 'resume_pos' => 0]
]);
$handle = @opendir($ftpPath, $ctx);
if ($handle) {
    while (($file = readdir($handle)) !== false) {
        if ($file !== '.' && $file !== '..') echo "$file<br>";
    }
    closedir($handle);
} else {
    echo 'FTP 連線失敗';
}

四、HTTP 目錄列表 (需伺服器開啟 Indexes)

$handle = @opendir('https://example.com/assets/');
if ($handle) {
    while (($file = readdir($handle)) !== false) echo "$file<br>";
    closedir($handle);
}

五、遞迴掃描基礎實作 (深度優先)

function scanDirRecursive(string $dir, int $depth = 0): array {
    $handle = @opendir($dir);
    if (!$handle) return [];

    $result = [];
    while (($entry = readdir($handle)) !== false) {
        if ($entry === '.' || $entry === '..') continue;
        $full = $dir . '/' . $entry;
        $item = ['name' => $entry, 'path' => $full, 'depth' => $depth];
        if (is_dir($full)) {
            $item['type'] = 'dir';
            $item['children'] = scanDirRecursive($full, $depth + 1);
        } else {
            $item['type'] = 'file';
            $item['size'] = filesize($full);
        }
        $result[] = $item;
    }
    closedir($handle);
    return $result;
}

print_r(scanDirRecursive('src'));

六、資源管理最佳實務

七、現代替代:DirectoryIterator (SPL)

foreach (new DirectoryIterator('src') as $file) {
    if ($file->isDot()) continue;
    echo $file->getFilename() . ' - ' . $file->getSize() . ' bytes<br>';
    // 直接取得 SplFileInfo 方法:isDir(), getMTime(), getPerms(), isReadable()...
}
  • **自動實作 Iterator/SeekableIterator/Countable**
  • **自動過濾 . 和 ..** (需手動 isDot() 或 FilesystemIterator::SKIP_DOTS)
  • **物件導向、型別安全、可直接串流處理**

八、常見錯誤代碼與排查

原則做法
必須關閉所有路徑 (正常/break/continue/exception) 皆呼叫 closedir($handle)
try/finallyPHP 5.5+ 建議包裹確保釋放
避免洩漏長期運行腳本 (daemon) 定期檢查 get_resources() 未釋放 handle
錯誤抑制用 @opendir() 避免 E_WARNING 干擾輸出,自行檢查回傳值
警告/錯誤原因排查
failed to open dir: Permission denied目錄權限 700/500、SELinux/AppArmor 限制is_readable()、檢查 ACL、調整 context
failed to open dir: No such file or directory路徑錯誤、相對路徑基準不對用 realpath() 正規化
ftp:// wrapper disabledphp.ini allow_url_fopen=Off 或未編譯 ftp 擴充啟用 allow_url_fopen、安裝 php-ftp

opendir() 以**極簡 API、通用封裝協定支援、手動資源控制**成為底層目錄操作基石;現代專案優先使用 DirectoryIterator 享受物件導向優勢,僅在需**自定遞迴邏輯、串流上下文控制、舊版本相容**時直接呼叫。

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