PHP项目目录与scandir

wen PHP项目 7

本文目录导读:

PHP项目目录与scandir

  1. 常见 PHP 项目目录结构
  2. scandir() 函数详解
  3. 实用示例
  4. 性能优化建议
  5. 实际应用场景

我来详细介绍 PHP 项目目录结构管理和 scandir 函数的使用。

常见 PHP 项目目录结构

基础项目结构

my-project/
├── public/              # 公共访问目录(Document Root)
│   ├── index.php
│   ├── css/
│   ├── js/
│   └── images/
├── src/                 # 源代码
│   ├── Controllers/
│   ├── Models/
│   ├── Views/
│   └── Helpers/
├── config/              # 配置文件
│   ├── database.php
│   └── app.php
├── vendor/              # 第三方库(Composer)
├── logs/                # 日志文件
├── uploads/             # 上传文件
├── cache/               # 缓存
├── tests/               # 测试文件
├── composer.json
├── .env                 # 环境变量
└── .gitignore

框架项目结构示例(Laravel)

laravel-project/
├── app/
│   ├── Http/
│   │   └── Controllers/
│   ├── Models/
│   └── Providers/
├── bootstrap/
├── config/
├── database/
│   ├── migrations/
│   └── seeds/
├── public/
├── resources/
│   ├── views/
│   └── lang/
├── routes/
├── storage/
├── tests/
└── vendor/

scandir() 函数详解

基本语法

scandir(string $directory, int $sorting_order = SCANDIR_SORT_ASCENDING, ?resource $context = null): array|false

基本用法

// 扫描当前目录
$files = scandir('./');
print_r($files);
// 扫描指定目录
$files = scandir('/var/www/html/project');
print_r($files);

排序选项

// 默认升序排序
$files_asc = scandir('./uploads', SCANDIR_SORT_ASCENDING);
// 降序排序
$files_desc = scandir('./uploads', SCANDIR_SORT_DESCENDING);
// 不排序
$files_none = scandir('./uploads', SCANDIR_SORT_NONE);

实用示例

获取目录中所有文件(排除 . 和 ..)

function getDirectoryFiles(string $dir): array {
    $files = scandir($dir);
    // 过滤掉 . 和 ..
    $files = array_diff($files, ['.', '..']);
    // 重新索引数组
    return array_values($files);
}
// 使用
$files = getDirectoryFiles('./uploads');
print_r($files);

递归扫描目录

function scanDirectoryRecursive(string $dir): array {
    $result = [];
    $files = scandir($dir);
    foreach ($files as $file) {
        if ($file === '.' || $file === '..') continue;
        $path = $dir . DIRECTORY_SEPARATOR . $file;
        if (is_dir($path)) {
            $result[$file] = scanDirectoryRecursive($path);
        } else {
            $result[] = $file;
        }
    }
    return $result;
}
// 使用
$structure = scanDirectoryRecursive('./project');
print_r($structure);

按文件类型筛选

function getFilesByExtension(string $dir, string $extension): array {
    $files = scandir($dir);
    $filtered = [];
    foreach ($files as $file) {
        $path = $dir . DIRECTORY_SEPARATOR . $file;
        if (is_file($path) && pathinfo($file, PATHINFO_EXTENSION) === $extension) {
            $filtered[] = $file;
        }
    }
    return $filtered;
}
// 获取所有 PHP 文件
$php_files = getFilesByExtension('./src', 'php');
// 获取所有图片文件
$images = getFilesByExtension('./uploads', 'jpg');

安全和错误处理

function safeScanDir(string $dir): array {
    // 检查目录是否存在
    if (!is_dir($dir)) {
        throw new InvalidArgumentException("目录不存在: $dir");
    }
    // 检查读取权限
    if (!is_readable($dir)) {
        throw new RuntimeException("无法读取目录: $dir");
    }
    $files = scandir($dir);
    if ($files === false) {
        throw new RuntimeException("扫描目录失败: $dir");
    }
    return array_diff($files, ['.', '..']);
}
try {
    $files = safeScanDir('./uploads');
    print_r($files);
} catch (Exception $e) {
    echo "错误: " . $e->getMessage();
}

文件信息增强版

function getDetailedFileInfo(string $dir): array {
    $files = scandir($dir);
    $details = [];
    foreach ($files as $file) {
        if ($file === '.' || $file === '..') continue;
        $path = $dir . DIRECTORY_SEPARATOR . $file;
        $details[] = [
            'name' => $file,
            'path' => $path,
            'type' => is_dir($path) ? 'directory' : 'file',
            'size' => is_file($path) ? filesize($path) : 0,
            'modified' => filemtime($path),
            'extension' => pathinfo($file, PATHINFO_EXTENSION),
            'permissions' => substr(sprintf('%o', fileperms($path)), -4)
        ];
    }
    return $details;
}
// 使用
$file_info = getDetailedFileInfo('./project');
print_r($file_info);

性能优化建议

// 对于大目录,使用 DirectoryIterator
function efficientScanDir(string $dir): array {
    $files = [];
    $iterator = new DirectoryIterator($dir);
    foreach ($iterator as $fileInfo) {
        if ($fileInfo->isDot()) continue;
        $files[] = $fileInfo->getFilename();
    }
    return $files;
}
// 使用 Glob 进行模式匹配
function scanDirWithPattern(string $pattern): array {
    return glob($pattern);
}
// 示例
$php_files = scanDirWithPattern('./src/**/*.php');
$json_files = scanDirWithPattern('./config/*.json');

实际应用场景

文件管理器

class FileManager {
    private string $basePath;
    public function __construct(string $basePath) {
        $this->basePath = rtrim($basePath, '/');
    }
    public function listDirectory(string $subDir = ''): array {
        $fullPath = $this->basePath . ($subDir ? '/' . $subDir : '');
        if (!is_dir($fullPath)) {
            return ['error' => '目录不存在'];
        }
        $files = scandir($fullPath);
        $items = [];
        foreach ($files as $file) {
            if ($file === '.' || $file === '..') continue;
            $path = $fullPath . '/' . $file;
            $items[] = [
                'name' => $file,
                'type' => is_dir($path) ? 'folder' : 'file',
                'size' => is_file($path) ? filesize($path) : null,
                'modified' => date('Y-m-d H:i:s', filemtime($path))
            ];
        }
        return $items;
    }
}
// 使用
$fm = new FileManager('/var/www/uploads');
$files = $fm->listDirectory('images');

这个指南涵盖了 PHP 项目目录结构和 scandir 函数的主要用法,根据具体需求,你可以组合使用这些方法来处理文件和目录操作。

抱歉,评论功能暂时关闭!