雖然 dBase 格式已較少見,但 PHP 仍內建完整支援;目錄操作、檔案屬性、權限管理則是伺服器端開發日常必備。本文整理 dBase 資料表操作、目錄掃描、檔案權限/屬性/類型判斷、磁碟空間等函數,附實戰範例。
注意:PHP 7+ 需安裝 PECL `dbase` 擴展 (`pecl install dbase`),預設不內建。
<?php
// 1. 建立資料表結構
$fields = [
['name' => 'id', 'type' => 'N', 'length' => 10, 'precision' => 0],
['name' => 'name', 'type' => 'C', 'length' => 50],
['name' => 'email', 'type' => 'C', 'length' => 100],
['name' => 'created', 'type' => 'D', 'length' => 8], // YYYYMMDD
];
$db = dbase_create('users.dbf', $fields);
if (!$db) die("建立失敗");
// 2. 開啟現有資料表 (1=唯讀, 2=讀寫)
$db = dbase_open('users.dbf', 2);
if (!$db) die("開啟失敗");
// 3. 新增記錄 (陣列順序需符合欄位順序)
$record = [1, '張三', 'zhang@example.com', date('Ymd')];
dbase_add_record($db, $record);
// 4. 讀取記錄 (索引從 1 開始)
$row = dbase_get_record($db, 1);
print_r($row); // ['id'=>1, 'name'=>'張三', ...]
// 5. 更新記錄 (需先讀取、修改、再寫回 - dbase 無直接 update)
$row['email'] = 'new@example.com';
dbase_replace_record($db, $row, 1); // 需 dbase 7+ 或自行實作
// 6. 刪除記錄 (標記刪除,需 pack 真正移除)
dbase_delete_record($db, 1);
dbase_pack($db); // 物理移除已刪除記錄
// 7. 遍歷所有記錄
$count = dbase_numrecords($db);
for ($i = 1; $i <= $count; $i++) {
$rec = dbase_get_record($db, $i);
if ($rec['deleted']) continue; // 跳過已刪除
// 處理...
}
// 8. 關閉
dbase_close($db);
?>
| 函數 | 功能 | 備註 |
|---|---|---|
| dbase_create($file, $fields) | 建立 .dbf 檔 | $fields: [['name','type','len','prec'],...] |
| dbase_open($file, $mode) | 開啟資料表 | mode: 0=無, 1=讀, 2=寫, 3=讀寫 |
| dbase_close($db) | 關閉資料表 | |
| dbase_pack($db) | 清理已刪除記錄 | 物理重組檔案 |
| dbase_add_record($db, $arr) | 新增記錄 | 索引順序對應欄位 |
| dbase_delete_record($db, $num) | 標記刪除 | 需 pack 才真正移除 |
| dbase_get_record($db, $num) | 取得記錄 (含 deleted 欄位) | 索引從 1 開始 |
| dbase_numfields($db) | 欄位數 | |
| dbase_numrecords($db) | 記錄數 (含已刪除) | |
| dbase_replace_record($db, $arr, $num) | 更新記錄 | PHP 7+ dbase 擴展支援 |
$handle = opendir('/var/www/html');
if ($handle) {
while (($entry = readdir($handle)) !== false) {
if ($entry !== '.' && $entry !== '..') {
$fullPath = '/var/www/html/' . $entry;
echo $entry . ($entry === 'dir' ? '/' : '') . "\n";
}
}
closedir($handle);
}
// 現代物件導向方式 (推薦)
$dir = new DirectoryIterator('/var/www/html');
foreach ($dir as $fileInfo) {
if (!$fileInfo->isDot()) {
echo $fileInfo->getFilename() . ($fileInfo->isDir() ? '/' : '') . "\n";
}
}
// 遞迴掃描
$rdi = new RecursiveDirectoryIterator('/var/www/html');
$iter = new RecursiveIteratorIterator($rdi);
foreach ($iter as $fileInfo) {
if (!$fileInfo->isDot()) echo $fileInfo->getPathname() . "\n";
}
echo getcwd(); // 取得目前工作目錄
chdir('/tmp'); // 切換工作目錄
echo getcwd(); // /tmp
$handle = opendir('/path');
readdir($handle); // 讀幾個
rewinddir($handle); // 重置到開頭
readdir($handle); // 再次從頭讀取
| 函數 | 功能 | 範例 |
|---|---|---|
| chmod($file, $mode) | 更改權限 | chmod('file.txt', 0644) |
| chown($file, $user) | 更改擁有者 | chown('file.txt', 'www-data') |
| chgrp($file, $group) | 更改群組 | chgrp('file.txt', 'www-data') |
| fileperms($file) | 取得權限 (int) | substr(sprintf('%o', fileperms('f')), -4) → "0644" |
| fileowner($file) | 取得 UID | 1000 |
| filegroup($file) | 取得 GID | 1000 |
$file = '/etc/passwd';
is_file($file) // true 一般檔案
is_dir($file) // false 目錄
is_link($file) // false 符號連結
is_readable($file) // true 可讀
is_writable($file) // false 可寫
is_executable($file)// false 可執行
file_exists($file) // true 存在 (含目錄、連結)
// 類型字串
filetype($file); // "file" / "dir" / "link" / "fifo" / "block" / "char" / "unknown"
fileinode($file) // inode 號碼
// 硬連結計數:stat($file)['nlink']
// 符號連結目標:readlink($linkPath)
filesize($file) // 位元組數 (int,>2GB 可能溢位,用 stat()['size'])
fileatime($file) // 最後存取時間
filemtime($file) // 最後修改時間 (最常用)
filectime($file) // 最後狀態變更時間
touch($file) // 更新 atime/mtime 為現在
touch($file, time() - 86400); // 指定時間
$dir = '/';
echo "總計: " . humanSize(disk_total_space($dir)) . "\n"; // 500 GB
echo "可用: " . humanSize(disk_free_space($dir)) . "\n"; // 120 GB
function humanSize($bytes) {
$units = ['B','KB','MB','GB','TB'];
$i = 0;
while ($bytes >= 1024 && $i < 4) { $bytes /= 1024; $i++; }
return round($bytes, 2) . ' ' . $units[$i];
}
<?php
// fix-permissions.php
$root = __DIR__;
$dirs = ['storage', 'bootstrap/cache', 'public/uploads'];
$files = ['.env'];
echo "修正目錄權限 775...\n";
foreach ($dirs as $d) {
$path = $root . '/' . $d;
if (is_dir($path)) {
chmod($path, 0775);
// 遞迴修正子目錄
$rdi = new RecursiveDirectoryIterator($path);
foreach (new RecursiveIteratorIterator($rdi) as $f) {
if ($f->isDir()) chmod($f->getPathname(), 0775);
else chmod($f->getPathname(), 0664);
}
}
}
echo "修正檔案權限 664...\n";
foreach ($files as $f) {
$path = $root . '/' . $f;
if (is_file($path)) chmod($path, 0664);
}
echo "設定擁有者 www-data:www-data...\n";
exec("chown -R www-data:www-data {$root}/storage {$root}/bootstrap/cache {$root}/public/uploads 2>/dev/null");
echo "完成。\n";
?>
dBase 雖舊但特定產業 (醫療、政府舊系統) 仍在使用,掌握其「記錄索引從 1 開始、刪除需 pack」特性即可。目錄操作**強烈推薦 SPL 迭代器** (`DirectoryIterator`, `RecursiveDirectoryIterator`),物件導向、記憶體效率高、支援鏈式操作。檔案屬性判斷善用 `is_*` 族群與 `filetype()`,權限操作注意 PHP 執行身分需有對應系統權限。磁碟空間監控可納入健康檢查機制,預警防止寫入失敗。