本文目录导读:

我来详细介绍 Symfony Finder 组件的迭代使用:
基础 Finder 迭代
use Symfony\Component\Finder\Finder;
$finder = new Finder();
$finder->files()->in('/path/to/directory');
// 直接迭代文件
foreach ($finder as $file) {
echo $file->getRealPath() . "\n";
echo $file->getFilename() . "\n";
}
常用的迭代方法
1 过滤迭代
$finder = new Finder();
// 只找 PHP 文件
$finder->files()
->in(__DIR__ . '/src')
->name('*.php')
->notName('*Test.php');
// 带条件的迭代
foreach ($finder as $file) {
// 只处理大于 1KB 的文件
if ($file->getSize() > 1024) {
echo $file->getFilename() . " - " . $file->getSize() . " bytes\n";
}
}
2 排序迭代
$finder->files()
->in('/path')
->sortByName(); // 按文件名排序
// 或
$finder->sortByModifiedTime(); // 按修改时间排序
foreach ($finder as $file) {
echo $file->getFilename() . " - " . date('Y-m-d H:i:s', $file->getMTime()) . "\n";
}
高级迭代模式
1 使用回调过滤
$finder = new Finder();
$finder->files()
->in('/path')
->filter(function (\SplFileInfo $file) {
// 只保留最近7天内修改的文件
if ($file->getMTime() > strtotime('-7 days')) {
return true;
}
return false;
});
// 迭代并处理
$finder->getIterator(); // 获取迭代器对象
2 深度控制
$finder->files()
->in('/project')
->depth('< 2') // 只搜索1-2层目录
->depth('>= 1') // 至少搜索1层
->depth(['< 3', '> 1']); // 2-3层
的迭代处理
$finder = new Finder();
$finder->files()
->in('/logs')
->name('*.log')
->size('> 100K'); // 大于100KB
$results = [];
foreach ($finder as $file) {
// 读取文件内容
$content = $file->getContents();
// 搜索特定内容
if (str_contains($content, 'ERROR')) {
$results[] = [
'file' => $file->getRealPath(),
'lines' => $this->getErrorLines($content)
];
}
}
性能优化迭代
1 批量处理
class FileBatchProcessor
{
private $batchSize = 100;
public function processFiles(Finder $finder, callable $callback): void
{
$batch = [];
$count = 0;
foreach ($finder as $file) {
$batch[] = $file;
$count++;
// 达到批次大小,处理batch
if ($count % $this->batchSize === 0) {
$callback($batch);
$batch = [];
}
}
// 处理剩余的
if (!empty($batch)) {
$callback($batch);
}
}
}
2 惰性迭代
// 转换为惰性集合
$files = iterator_to_array($finder);
$collection = new \Doctrine\Common\Collections\ArrayCollection($files);
$collection->map(function ($file) {
return [
'path' => $file->getRelativePathname(),
'size' => $file->getSize(),
'modified' => $file->getMTime()
];
});
多目录迭代
$finder = new Finder();
$finder->files()
->in(['/var/www/html', '/var/www/app'])
->exclude(['vendor', 'node_modules']);
// 并行处理不同目录
foreach ($finder as $file) {
$path = $file->getRelativePath();
switch (true) {
case str_starts_with($path, 'html/'):
// 处理 html 目录文件
break;
case str_starts_with($path, 'app/'):
// 处理 app 目录文件
break;
}
}
实用示例:文件校验器
class FileValidator
{
public function validateFiles(string $directory): array
{
$finder = new Finder();
$validator = new FileRulesValidator();
$finder->files()
->in($directory)
->name('*.php')
->notName('*Test.php');
$errors = [];
foreach ($finder as $file) {
// 逐行检查
$lines = file($file->getRealPath());
foreach ($lines as $lineNumber => $line) {
if (!$validator->validateLine($line)) {
$errors[] = [
'file' => $file->getRelativePathname(),
'line' => $lineNumber + 1,
'content' => trim($line)
];
}
}
}
return $errors;
}
}
注意事项
- 性能优化:对于大目录,使用
getIterator()而不是创建数组 - 内存管理:迭代过程中确保及时释放不用的文件句柄
- 异常处理:迭代时捕获异常,避免单个文件问题中断整个流程
foreach ($finder as $file) {
try {
// 处理文件
$content = $file->getContents();
// 处理逻辑...
} catch (\Throwable $e) {
// 记录错误但继续处理其他文件
Logger::error("处理文件失败: {$file->getRealPath()}", [
'error' => $e->getMessage()
]);
continue;
}
}
这样的迭代方式既高效又灵活,能处理各种文件搜索和处理需求。