支付宝扫一扫付款
微信扫一扫付款
(微信为保护隐私,不显示你的昵称)
Finder组件通过一个直观而流畅的接口来寻找文件和目录。
你可以通过下述两种方式安装:
通过Composer安装(Packagist上的symfony/finder
)
通过官方Git宝库(https://github.com/symfony/finder)
然后,包容vendor/autoload.php
文件,以开启Composer提供的自动加载机制。否则,你的程序将无法找到这个Symfony组件的类。
Finder
寻找文件和/或目录:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | use Symfony\Component\Finder\Finder;
$finder = new Finder();
$finder->files()->in(__DIR__);
foreach ($finder as $file) {
// Dump the absolute path / 剥离出绝对路径
var_dump($file->getRealPath());
// Dump the relative path to the file, omitting the filename
// 剥离出文件的相对路径,忽略文件名
var_dump($file->getRelativePath());
// Dump the relative path to the file
// 剥离出文件的相对路径
var_dump($file->getRelativePathname());
} |
$file
是 SplFileInfo
的一个实例,它继承了PHP自己的 SplFileInfo
以提供能够处理相对路径的方法。
上面代码递归地输出当前目录下的全部文件名。Finder类使用了fluent接口,因此所有方法返回的都是Finder实例。
一个Finder实例是一个PHP Iterator
。所以,不同于使用 foreach
来遍历Finder,你应该使用 iterator_to_array
方法把它转换成数组,或是使用 iterator_count
来取得item数量。
当要搜索多个位置并将它们传入 in()
方法时,程序内部会为每个位置创建一个独立的迭代器。由于 iterator_to_array
默认使用了结果数组的键,当转换成一个数组时,某些键可能会重复,它们的值会被覆写。将 false
作为第二参数传入 iterator_to_array
可以避免此种情况。
组件提供多种方式对你的结果进行过滤和归类。
location(位置)是唯一的强制项。它告诉finder要使用哪个目录进行搜索。
1 | $finder->in(__DIR__); |
通过链式调用(chaining calls)in()
可以在若干位置进行搜索:
1 2 3 4 5 | // search inside *both* directories / *两个* 目录中都会搜索
$finder->files()->in(array(__DIR__, '/elsewhere'));
// same as above / 效果同上
$finder->in(__DIR__)->in('/elsewhere'); |
使用通配符可在“pattern匹配”的目录中进行搜索:
1 | $finder->in('src/Symfony/*/*/Resources'); |
每个pattern至少会解析一个目录路径。
匹配时若要排除目录可以使用 exclude()
方法:
1 | $finder->in(__DIR__)->exclude('ruby'); |
对目录没有读取权限时也可以忽略此目录:
1 | $finder->ignoreUnreadableDirs()->in(__DIR__); |
由于Finder使用的是PHP迭代器,你可以传入任何支持 protocol 的URL:
1 | $finder->in('ftp://example.com/pub/'); |
Finder也可以和用户自定义的streams一起工作:
1 2 3 4 5 6 7 8 9 10 | use Symfony\Component\Finder\Finder;
$s3 = new \Zend_Service_Amazon_S3($key, $secret);
$s3->registerStreamWrapper('s3');
$finder = new Finder();
$finder->name('photos*')->size('< 100K')->date('since 1 hour ago');
foreach ($finder->in('s3://bucket-name') as $file) {
// ... do something with the file / 对文件进行处理
} |
阅读 Streams 文档以了解如何创建你自己的流。
默认时,Finder返回文件和目录;但是 files()
和 directories()
方法分别控制之:
1 2 3 | $finder->files();
$finder->directories(); |
如果你要跟随链接,使用 followLinks()
方法:
1 | $finder->files()->followLinks(); |
默认时,iterator会忽略常见的VCS文件。使用 ignoreVCS()
方法即可改变此种行为:
1 | $finder->ignoreVCS(false); |
搜索结果根据(文件/目录的)name和type进行归类(目录在先,然后是文件):
1 2 3 | $finder->sortByName();
$finder->sortByType(); |
注意 sort*
方法需要得到所有匹配的元素才能完成工作。对于巨大的iterators,它会非常慢。
你也可以定义自己的 sort()
方法:
要通过文件名来限制文件,使用 name()
方法:
1 | $finder->files()->name('*.php'); |
name()
方法接收globs(通配符),字符串,或是regexes(正则表达式):
1 | $finder->files()->name('/\.php$/'); |
notName()
方法可以排除匹配到pattern的文件:
1 | $finder->files()->notName('*.rb'); |
要通过内容来限制文件,使用 contains()
方法:
1 | $finder->files()->contains('lorem ipsum'); |
contains()
方法接收字符串,或是regexes(正则表达式):
1 | $finder->files()->contains('/lorem\s+ipsum$/i'); |
notContains()
方法可以排除匹配到给定pattern的文件:
1 | $finder->files()->notContains('dolor sit amet'); |
要通过Path(路径)来限制文件,使用 path()
方法:
1 2 3 4 5 6 | // matches files that contain "data" anywhere in their paths (files or directories)
// 匹配那些路径中包含有“data”的文件(或目录)
$finder->path('data');
// for example this will match data/*.xml and data.xml if they exist
// 例如,这将匹配 data/*.xml 以及 data.xml,如果存在的话
$finder->path('data')->name('*.xml'); |
在所有平台上,斜杠(/
)应被当作目录分隔符来使用。
path()
方法接收一个字符串或者一个正则表达式:
1 2 | $finder->path('foo/bar');
$finder->path('/^foo\/bar/'); |
在内部,字符串会被进行斜杠转义并添加分隔符,然后转换成正则表达式:
1 2 | dirname ===> /dirname/
a/b/c ===> /a\/b\/c/ |
notPath()
方法根据路径来排除文件:
1 | $finder->notPath('other/dir'); |
要通过大小来限制文件,使用 size()
方法:
1 | $finder->files()->size('< 1.5K'); |
通过链式调用来限制文件的容量范围:
1 | $finder->files()->size('>= 1K')->size('<= 2K'); |
比较运算符可以是以下任意一种:>
, >=
, <
, <=
, ==
, !=
。
目标值可以使用“量级”单位,KB (k
, ki
), MB (m
, mi
), 或GB (g
, gi
)。那些使用了 i
后缀的单位,用的是专业的 2**n
版本,遵照 IEC standard。
要通过“最后修改日期”来限制文件,使用 date()
方法:
1 | $finder->date('since yesterday'); |
比较运算符可以是以下任意一种:>
, >=
, <
, <=
, ==
。你也可以使用 since
或 after
作为 >
, 和 until
的假名,或者用 before
作为 <
的假名。
目标值可以使用任何支持 strtotime 函数的日期格式。
默认时,Finder递归地遍历目录。要限制遍历的目录层数,使用 depth()
:
1 2 | $finder->depth('== 0');
$finder->depth('< 3'); |
要通过你自己的策略来限制匹配到的文件,使用 filter()
:
1 2 3 4 5 6 7 8 | $filter = function (\SplFileInfo $file)
{
if (strlen($file) > 10) {
return false;
}
};
$finder->files()->filter($filter); |
filter()
方法接收一个 Closure 作为参数。文件的每一次匹配,它都会被调用,其参数文件将作为 SplFileInfo
实例。如果Closure返回 false
,则文件将被排除出结果集。
返回文件的内容可以通过 getContents()
来读取:
1 2 3 4 5 6 7 8 9 10 | use Symfony\Component\Finder\Finder;
$finder = new Finder();
$finder->files()->in(__DIR__);
foreach ($finder as $file) {
$contents = $file->getContents();
// ...
} |
本文,包括例程代码在内,采用的是 Creative Commons BY-SA 3.0 创作共用授权。