Компонент Finder

Компонент Finder находит файлы и каталоги через интуитивный fluent интерфейс.

Установка

1
$ composer require symfony/finder

Также вы можете клонировать репозиторий https://github.com/symfony/finder.

Note

If you install this component outside of a Symfony application, you must require the vendor/autoload.php file in your code to enable the class autoloading mechanism provided by Composer. Read this article for more details.

Применение

Класс Finder находит файлы и/или каталоги:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
use Symfony\Component\Finder\Finder;

$finder = new Finder();
$finder->files()->in(__DIR__);

foreach ($finder as $file) {
    // Сбрасывает абсолютный путь
    var_dump($file->getRealPath());

    // Сбрасывает относительный путь к файлу, опустив имя файла
    var_dump($file->getRelativePath());

    // Сбрасывает относительный путь к файлу
    var_dump($file->getRelativePathname());
}

$file является экземпляром SplFileInfo, который расширяет собственный SplFileInfo PHP, чтобы предоставить методы для работы с относительными путями.

Код выше отображает имена всех файлов в текущем каталоге в обратном порядке. Класс Поисковика использует свободный интерфейс, так что все методы возвращают экземпляр Поисковика.

Tip

Экземпляр Поисковика - это Iterator. Так что в дополнение к итерации Поисковика с помощью foreach, вы также можете конвертировать его в массив методом iterator_to_array, или получить количество объектов с iterator_count.

Caution

Объект Finder не перезагружает внутреннее состояние автоматически. Это означает, что вам нужно создать новый экземпляр, если вы не хотите получить смешнанный результат.

Caution

При поиске в нескольких локациях, переданных методу in(), для каждой локации внутренне создаётся отдельный итератор. Это означает, что у нас несколько наборов результатов собираются в один. Так как iterator_to_array использует ключи наборов результатов по умолчанию при конвертации в массив, некоторые ключи могут быть продублированы, а их значения - перезаписаны. Этого можно избежать передав false в качестве второго параметра iterator_to_array.

Критерии

Существует множество способов фильтровать и сортировать ваши результаты. Вы можете также использовать метод hasResults(), чтобы проверить, существует ли файл или каталог, соответствующий критериям поиска.

Локация

Локация - единственный обязательный критерий. Она сообщает поискоивку, какой каталог использовать для поиска:

1
$finder->in(__DIR__);

Искать в нескльких локациях, изменяя вызов на in():

1
2
3
4
5
// искать внутри *обоих* каталогов
$finder->in(array(__DIR__, '/elsewhere'));

// то же, что и выше
$finder->in(__DIR__)->in('/elsewhere');

Используйте символы-заполнители, чтобы искать в каталогах, соответствующих шаблону:

1
$finder->in('src/Symfony/*/*/Resources');

Каждый шаблон должен разрешать как минимум один путь каталога.

Исключить каталоги, совпадающие с методом exclude():

1
2
// каталоги, переданные в качестве аргумента, должны быть связаны с теми, что определены в методе in()
$finder->in(__DIR__)->exclude('ruby');

Также возможно игнорировать каталоги, на чтение которых у вас нет разрешения:

1
$finder->ignoreUnreadableDirs()->in(__DIR__);

Так как Поисковик использует PHP итераторы, вы можете передать любой URL, поддерживаемым protocol:

1
2
3
4
5
// всегда добавляйте закрывающий слеш, когда ищете dir корна FTP
$finder->in('ftp://example.com/');

// вы можете также искать в каталоге FTP
$finder->in('ftp://example.com/pub/');

И это также работает с потоками, определёнными пользователями:

 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) {
    // ... сделать что-то с файлом
}

Note

Простите документацию Потоки, чтобы узнать, как создавать собственные потоки.

Файлы или каталоги

По умолчанию, Поисковик возвращает файлы и каталоги; но методы files() и directories() контролируют это:

1
2
3
$finder->files();

$finder->directories();

Если вы хотите следовать ссылкам, используйте метод followLinks():

1
$finder->files()->followLinks();

По умолчанию, итератор игнорирует поплуярные VCS файлы. Это можно изменить методом ignoreVCS():

1
$finder->ignoreVCS(false);

Сортировка

Сортируйте результат по имени или типу (вначале каталоги, потом файлы):

1
2
3
$finder->sortByName();

$finder->sortByType();

Tip

По умолчанию метод sortByName() использует функцию PHP strcmp (то есть, file1.txt, file10.txt, file2.txt). Передайте аргумент true для использования алгоритма PHP Естественный порядок сортировки (то есть, file1.txt, file2.txt, file10.txt).

New in version 4.2: Возможность использования естественного порядка сортировки появилась в Symfony 4.2.

Вы можете также определить собственный алгоритм сортировки в методе sort():

1
2
3
$finder->sort(function (\SplFileInfo $a, \SplFileInfo $b) {
    return strcmp($a->getRealPath(), $b->getRealPath());
});

Note

Заметьте, что методы sort* должны получить все подходящие элементы для своей работы. Для больших итераторов это может быть медленно.

Имя файла

Ограничьте файлы по имени методом name():

1
$finder->files()->name('*.php');

Метод name() принимает маски, строки или регулярные выражения:

1
$finder->files()->name('/\.php$/');

Метод notName() исключает файлы, совпадающие со схемой:

1
$finder->files()->notName('*.rb');

Содержание файла

Ограничьте файлы по содержанию, методом contains():

1
$finder->files()->contains('lorem ipsum');

Метод contains() принимает строки или регулярные выражения:

1
$finder->files()->contains('/lorem\s+ipsum$/i');

Метод notContains() исключает файлы, содержащие заданную схему:

1
$finder->files()->notContains('dolor sit amet');

Путь

Ограничьте файлы и папки по пути, методом path():

1
2
3
4
// сопоставляет файлы, содержащие "data" где-либо в их путях (файлах или каталогах)
$finder->path('data');
// например, это будет соответстсовать 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');

Оператор сравнения может быть чем-либо из следующего: >, >=, <, <=, ==, !=.

Целевое значение может использовать величины килобайтов (k, ki), мегабайтов (m, mi), или гигабайтов (g, gi). Те, что имеют суффикс i, используют соответствующую версию 2**n в соответствии со стандартом IEC.

Данные файла

Ограничьте файлы по датам последних изменений, методом date()

1
$finder->date('since yesterday');

Оператор сравнения может быть любым из следующих: >, >=, <, <=, ==. Вы можете также использовать since или after в качестве дополнительного имени >, и until или before в качестве дополнительного имени <.

Целевое значение может быть любыми данными, поддерживаемыми функцией strtotime.

Глубина каталога

По умолчанию, Поисковик траверсирует каталоги в обратном порядке. Ограничьте глубину траверсирования методом 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 в качестве экземпляра. Файл исключается из набора результатов, если замыкание возвращает 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();

    // ...
}

Эта документация является переводом официальной документации Symfony и предоставляется по свободной лицензии CC BY-SA 3.0.