Компонент Finder

Дата оновлення перекладу 2024-05-02

Компонент Finder

Компонент Finder знаходить файли та каталоги, засновуючись на різних критеріях (імені, розмірі файлу, часу зміни та ін.) через текучий інтерфейс.

Установка

1
$ composer require symfony/finder

Note

Якщо ви встановлюєте цей компонент поза додатком Symfony, вам потрібно підключити файл vendor/autoload.phpу вашому коді для включення механізму автозавантаження класів, наданих Composer. Детальніше можна прочитати у цій статті.

Застосування

Клас 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__);

// перевірити, чи є результати пошуку
if ($finder->hasResults()) {
    // ...
}

foreach ($finder as $file) {
    $absoluteFilePath = $file->getRealPath();
    $fileNameWithExtension = $file->getRelativePathname();

    // ...
}

Змінна $file є екземпляром SplFileInfo, який розширює власний SplFileInfo PHP, щоб надати методи для роботи з відносними шляхами.

Caution

Обʼєкт Finder не перезавантажує внутрішній стан автоматично. Це означає, що вам потрібно створити новий екземпляр, якщо ви не хочете отримати змішаний результат.

Пошук файлів та каталогів

Компонент надає багато методів для визначення критеріїв пошуку. Всі вони можуть бути у ланцюжку, так як реалізують текучий інтерфейс.

Локація

Локація - єдиний обовʼязковий критерій. Вона повідомляє пошуковику, який каталог використовувати для пошуку:

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
3
// каталоги, передані в якості аргументу, повинні бути повʼязані з тими, що визначені
 в методі in()
$finder->in(__DIR__)->exclude('ruby');

Також можливо ігнорувати каталоги, на читання яких у вас немає дозволу:

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

Так як Finder використовує PHP ітератори, ви можете передати будь-який URL, що підтримується PHP-обгорткою для поротоколів типу URL (ftp://, zlib://, та ін.):

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
11
use Symfony\Component\Finder\Finder;

// зареєструвати обгортку 's3://' з офіційним AWS SDK
$s3Client = new Aws\S3\S3Client([/* config options */]);
$s3Client->registerStreamWrapper();

$finder = new Finder();
$finder->name('photos*')->size('< 100K')->date('since 1 hour ago');
foreach ($finder->in('s3://bucket-name') as $file) {
    // ... зробити щось з файлм
}

See also

Прочитайте документацію PHP-потоки, щоб дізнатися, як створювати власні потоки.

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

За замовчуванням. Пошуковик повертає і файли, і каталлоги. Якщо вам потрібні лише файли, або лише каталоги, використовуйте методи files() і directories():

1
2
3
4
5
// шукати лише файли; ігнорувати каталоги
$finder->files();

// шукати лише каталоги; ігнорувати файли
$finder->directories();

Якщо ви хочете слідувати символьним посиланням, використайте метод followLinks():

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

Файли контролю версій

Системи контролю версій (або скорочено "VCS"), такі як Git та Mercurial, створюють спеціальні файли для зберігання своїх метаданих. Ці файли ігноруються при пошуку файлів та каталогів за замовчуванням, але ви можете змінити це методом ignoreVCS():

1
$finder->ignoreVCS(false);

Якщо пошуковий каталог та його підкаталоги містять файли .gitignore, ви можете повторно використати ці два правила, щоб виключити файли та каталоги з результатів, методом ignoreVCSIgnored():

1
2
// виключити files/directories, що співпадають з патернами .gitignore
$finder->ignoreVCSIgnored(true);

Правила каталогу завжди головують над правилами батьківських каталогів.

Note

Git шукає файли .gitignore, починаючи з кореневого каталогу сховища. Поведінка Пошуковика Symfony відрізняється - він шукає файли .gitignore, починаючи з каталогу, використовуваного для пошуку файлів/каталогів. Щоб відповідати поведінці Git, вам потрібно чітко шукати з кореня сховища Git.

Імʼя файлу

Знайдіть файли за іменем методом name():

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

Метод name() приймає глобальні вирази, рядки, регулярні вирази та масиви глобальних або регулярних виразів:

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

Багато імен файлів може бути визначено шляхом створення ланцюжку викликів або передачі масиву:

1
2
3
4
$finder->files()->name('*.php')->name('*.twig');

// те ж саме, що і вище
$finder->files()->name(['*.php', '*.twig']);

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

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

Багато імен файлів може бути виключено шляхом створення ланцюжку викликів або передачі масиву:

1
2
3
4
$finder->files()->notName('*.rb')->notName('*.py');

// те ж саме, що і вище
$finder->files()->notName(['*.rb', '*.py']);

Зміст файлу

Знайдіть файли за змістом методом 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');

Використовуйте слеш праворуч (тобто, /) в якості роздільнику каталогів на всіх платформах, включно з Windows. Компонент проведе необхідні перетворення внутрішньо.

Метод path() приймає рядок, регулярний вираз або масив рядків чи регулярних виразів:

1
2
$finder->path('foo/bar');
$finder->path('/^foo\/bar/');

Багато шляхів може бути визначено шляхом створення ланцюжку викликів або передачі масиву:

1
2
3
4
$finder->path('data')->path('foo/bar');

// те ж саме, що і вище
$finder->path(['data', 'foo/bar']);

Внутрішньо, рядки перетворюються на регулярні вирази, екрануючи слеші та додаючи розділювачі:

?????????? ?????. ???????????????? ?????????? ?????
dirname /dirname/
a/b/c /a\/b\/c/

Метод notPath() виключає файли за шляхом:

1
$finder->notPath('other/dir');

Багато шляхів можна виключити шляхом створення ланцюжку викликів або передачі масиву:

1
2
3
4
$finder->notPath('first/dir')->notPath('other/dir');

// те ж саме, що і вище
$finder->notPath(['first/dir', 'other/dir']);

Розмір файлу

Знайдіть файли за розміром методом size():

1
$finder->files()->size('< 1.5K');

Обмежте за діапазаном розміру, створивши ланцюжок викликів або передавши масив:

1
2
3
4
$finder->files()->size('>= 1K')->size('<= 2K');

// те ж саме, що і вище
$finder->files()->size(['>= 1K', '<= 2K']);

Оператор порівняння може бути чимось з наступного: >, >=, <, <=, ==, !=.

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

Дата файлу

Знайдіть файли за датами останніх змін методом date() :

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

Обмежте за діапазоном даних шляхом створення ланцюжку викликів або передачі масиву:

1
2
3
4
$finder->date('>= 2018-01-01')->date('<= 2018-12-31');

// те ж саме, що і вище
$finder->date(['>= 2018-01-01', '<= 2018-12-31']);

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

Цільове значення може бути будь-якими даними, що підтримуються функцією 9d0b4fb14317a67f93ec6670e16d9026c050aaea.

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

За замовчуванням, Пошуковик траверсує каталоги у зворотному порядку. Обмежте глибику траверсування методом depth():

1
2
3
// це розглядатиме лише файли/каталоги, які є прямими дочірніми
$finder->depth('== 0');
$finder->depth('< 3');

Обмежте за діапазоном глибини шляхом створення ланцюжку викликів або передачі масиву:

1
2
3
4
$finder->depth('> 2')->depth('< 5');

// те ж саме, що і вище
$finder->depth(['> 2', '< 5']);

Користувацьке фільтрування

Щоб відфільтрувати результати за власною стратегією, використайте filter():

1
2
3
4
5
6
7
8
$filter = function (\SplFileInfo $file)
{
    if (strlen($file) > 10) {
        return false;
    }
};

$finder->files()->filter($filter);

Метод filter() бере Замикання в якості другого аргументу. Для кожного файлу, що співпадає, він викликається з файлом SplFileInfo в якості екземпляра. Файл виключається з набору результатів, якщо замикання повертає false.

Метод filter() має другий необов'язковий аргумент для відсікання каталогів. Якщо він має значення true, цей метод повністю пропускає вилучені каталоги замість того, щоб траверсувати всю структуру файлів/каталогів і вилучати їх пізніше. За використання закриття, поверніть значення false для каталогів, які ви хочете відсекти.

Раннє відсікання каталогів може значно покращити продуктивність, залежно від ієрархії файлів/каталогів та кількості вилучених каталогів.

Сортування результатів

Відсортуйте результати за іменем або типом (спочатку каталоги, потім - файли):

1
2
3
4
5
$finder->sortByName();
$finder->sortByCaseInsensitiveName();
$finder->sortByExtension();
$finder->sortBySize();
$finder->sortByType();

Tip

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

Метод sortByCaseInsensitiveName() використовує нечутливу до регістру функцію PHP strcasecmp. Передайте true як її аргумент, щоб використати замість цього нечутливий до регістру PHP-алгоритм природного порядку сортування (тобто, функцію PHP strnatcasecmp).

Відсортуйте файли та каталоги за останнім доступом, зміні або часу зміни:

1
2
3
4
5
$finder->sortByAccessedTime();

$finder->sortByChangedTime();

$finder->sortByModifiedTime();

Ви також может визначити власний алгоритм сортування методом sort():

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

Ви можете змінити порядок будь-якого сортування, використовуючи метод reverseSorting():

1
2
// результати будуть відсортовані "від Z до A" замість "від A до Z" за замовчуванням
$finder->sortByName()->reverseSorting();

Note

Відмітьте, що методи sort* повинні отримати всі елементи, що співпадають, щоб працювати. Для великих ітераторів це буде повільно.

Перетворення результатів на масиви

Екземпляр Пошуковика - це PHP-клас IteratorAggregate. Тому, на додаток до ітерації foreach зверху результатів Пошуковика, ви також можете перетворити їх на масив за допомогою функції iterator_to_array, або отримати кількість обʼєктів за допомогою iterator_count.

Якщо ви викличете метод in() більше одного разу, щоб виконати пошук за багатьма локаціями, передайте false в якості другого параметра iterator_to_array, щоб уникнути проблем (окреми ітератор створюється для кожної локації, і якщо ви не передасте false до iterator_to_array, використовуються ключі наборів результатів, і деякі з них можуть бути дубльовані, а їх значення - перевизначені).

Читання змісту повернених файлів

Зміст повернених файлів можна прочитати за допомогою 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();

    // ...
}