Nette Documentation Preview

syntax
Finder: fájlok keresése
***********************

.[perex]
Olyan fájlokat kell találnia, amelyek megfelelnek egy adott maszknak? A Finder segít ebben. Ez egy sokoldalú és gyors eszköz a könyvtárstruktúra bejárására.


Telepítés:

```shell
composer require nette/utils
```

A példák feltételezik a következő alias létrehozását:

```php
use Nette\Utils\Finder;
```


Használat
---------

Először megmutatjuk, hogyan írhatja ki a `.txt` és `.md` kiterjesztésű fájlneveket az aktuális könyvtárban a [api:Nette\Utils\Finder] segítségével:

```php
foreach (Finder::findFiles(['*.txt', '*.md']) as $name => $file) {
	echo $file;
}
```

A keresés alapértelmezett könyvtára az aktuális könyvtár, de ezt megváltoztathatja az [in() vagy from() |#Hol kell keresni] metódusokkal. A `$file` változó a [#FileInfo] osztály példánya, rengeteg hasznos metódussal. A `$name` kulcsban a fájl elérési útja található stringként.


Mit kell keresni?
-----------------

A `findFiles()` metódus mellett létezik a `findDirectories()`, amely csak könyvtárakat keres, és a `find()`, amely mindkettőt keresi. Ezek a metódusok statikusak, így példány létrehozása nélkül hívhatók. A maszk paraméter opcionális, ha nem adja meg, mindent megkeres.

```php
foreach (Finder::find() as $file) {
	echo $file; // most minden fájl és könyvtár kiíródik
}
```

A `files()` és `directories()` metódusokkal kiegészítheti, hogy mi mást kell keresni. A metódusok ismételten hívhatók, és paraméterként maszkok tömbje is megadható:

```php
Finder::findDirectories('vendor') // minden könyvtár
	->files(['*.php', '*.phpt']); // plusz minden PHP fájl
```

A statikus metódusok alternatívája a példány létrehozása a `new Finder` segítségével (az így létrehozott friss objektum semmit sem keres), és a `files()` és `directories()` segítségével megadni, mit kell keresni:

```php
(new Finder)
	->directories()      // minden könyvtár
	->files('*.php');    // plusz minden PHP fájl
```

A maszkban használhat [helyettesítő karaktereket |#Helyettesítő karakterek] `*`, `**`, `?` és `[...]`. Akár könyvtárakat is megadhat, például a `src/*.php` megkeresi az összes PHP fájlt a `src` könyvtárban.

A szimbolikus linkek szintén könyvtárnak vagy fájlnak minősülnek.


Hol kell keresni?
-----------------

A keresés alapértelmezett könyvtára az aktuális könyvtár. Ezt az `in()` és `from()` metódusokkal változtathatja meg. Ahogy a metódusnevekből is látható, az `in()` csak az adott könyvtárban keres, míg a `from()` annak alkönyvtáraiban is keres (rekurzívan). Ha rekurzívan szeretne keresni az aktuális könyvtárban, használhatja a `from('.')`-ot.

Ezek a metódusok többször is hívhatók, vagy több elérési utat átadhat nekik tömbként, a fájlok ezután minden könyvtárban keresve lesznek. Ha valamelyik könyvtár nem létezik, `Nette\UnexpectedValueException` kivétel dobódik.

```php
Finder::findFiles('*.php')
	->in(['src', 'tests']) // közvetlenül keres a src/ és tests/ könyvtárakban
	->from('vendor');      // a vendor/ alkönyvtáraiban is keres
```

A relatív elérési utak az aktuális könyvtárhoz képest relatívak. Természetesen abszolút elérési utakat is meg lehet adni:

```php
Finder::findFiles('*.php')
	->in('/var/www/html');
```

Az elérési úton lehet használni [helyettesítő karaktereket |#Helyettesítő karakterek] `*`, `**`, `?`. Így például a `src/*/*.php` elérési út segítségével keresheti az összes PHP fájlt a `src` könyvtár második szintű könyvtáraiban. A `**` karakter, amit globstarnak neveznek, egy erős aduász, mert lehetővé teszi az alkönyvtárakban való keresést is: a `src/**/tests/*.php` segítségével keresi az összes PHP fájlt a `tests` könyvtárban, amely a `src`-ben vagy annak bármely alkönyvtárában található.

Ellenben a `[...]` helyettesítő karakterek az elérési úton nem támogatottak, azaz nincs különleges jelentésük, hogy elkerüljük a nem kívánt viselkedést abban az esetben, ha például az `in(__DIR__)`-t keresi, és véletlenül az elérési úton `[]` karakterek lesznek.

Fájlok és könyvtárak mélységi keresésekor először a szülőkönyvtárat adja vissza, csak azután a benne lévő fájlokat, amit a `childFirst()` segítségével meg lehet fordítani.


Helyettesítő karakterek
-----------------------

A maszkban több speciális karaktert használhat:

- `*` - tetszőleges számú tetszőleges karaktert helyettesít (kivéve `/`)
- `**` - tetszőleges számú tetszőleges karaktert helyettesít, beleértve a `/`-t is (azaz többszintű keresés lehetséges)
- `?` - egy tetszőleges karaktert helyettesít (kivéve `/`)
- `[a-z]` - egy karaktert helyettesít a szögletes zárójelben lévő karakterlistából
- `[!a-z]` - egy karaktert helyettesít a szögletes zárójelben lévő karakterlistán kívül

Használati példák:

- `img/?.png` - egybetűs nevű fájlok `0.png`, `1.png`, `x.png`, stb.
- `logs/[0-9][0-9][0-9][0-9]-[01][0-9]-[0-3][0-9].log` - `YYYY-MM-DD` formátumú naplók
- `src/**/tests/*` - fájlok a `src/tests`, `src/foo/tests`, `src/foo/bar/tests` könyvtárakban és így tovább.
- `docs/**.md` - minden `.md` kiterjesztésű fájl a `docs` könyvtár összes alkönyvtárában


Kizárás
-------

Az `exclude()` metódussal kizárhat fájlokat és könyvtárakat a keresésből. Megadja a maszkot, amelynek a fájl nem felelhet meg. Példa `*.txt` fájlok keresésére, kivéve azokat, amelyek nevében `X` betű szerepel:

```php
Finder::findFiles('*.txt')
	->exclude('*X*');
```

A bejárt alkönyvtárak kihagyásához használja az `exclude()`-ot:

```php
Finder::findFiles('*.php')
	->from($dir)
	->exclude('temp', '.git')
```


Szűrés
------

A Finder több metódust kínál az eredmények szűrésére (azaz azok csökkentésére). Kombinálhatja őket és ismételten hívhatja.

A `size()` segítségével fájlméret szerint szűrünk. Így találunk 100 és 200 bájt közötti méretű fájlokat:

```php
Finder::findFiles('*.php')
	->size('>=', 100)
	->size('<=', 200);
```

A `date()` metódus a fájl utolsó módosításának dátuma szerint szűr. Az értékek lehetnek abszolútak vagy relatívak az aktuális dátumhoz és időhöz képest, például így találjuk meg az elmúlt két hétben módosított fájlokat:

```php
Finder::findFiles('*.php')
	->date('>', '-2 weeks')
	->from($dir)
```

Mindkét funkció érti a `>`, `>=`, `<`, `<=`, `=`, `!=`, `<>` operátorokat.

A Finder lehetővé teszi az eredmények szűrését saját funkciók segítségével is. A funkció paraméterként kap egy `Nette\Utils\FileInfo` objektumot, és `true`-t kell visszaadnia, hogy a fájl bekerüljön az eredmények közé.

Példa: olyan PHP fájlok keresése, amelyek tartalmazzák a `Nette` stringet (kis- és nagybetűk figyelmen kívül hagyásával):

```php
Finder::findFiles('*.php')
	->filter(fn($file) => strcasecmp($file->read(), 'Nette') === 0);
```


Mélységi szűrés
---------------

Rekurzív kereséskor beállíthatja a maximális bejárási mélységet a `limitDepth()` metódussal. Ha beállítja a `limitDepth(1)`-et, csak az első alkönyvtárakat járja be, a `limitDepth(0)` kikapcsolja a mélységi bejárást, és a -1 érték törli a korlátot.

A Finder lehetővé teszi saját funkciókkal eldönteni, melyik könyvtárba lépjen be a bejárás során. A funkció paraméterként kap egy `Nette\Utils\FileInfo` objektumot, és `true`-t kell visszaadnia, hogy belépjen a könyvtárba:

```php
Finder::findFiles('*.php')
	->descentFilter(fn($file) => $file->getBasename() !== 'temp');
```


Rendezés
--------

A Finder több funkciót is kínál az eredmények rendezésére.

A `sortByName()` metódus az eredményeket fájlnevek szerint rendezi. A rendezés naturális, azaz helyesen kezeli a számokat a nevekben, és például a `foo1.txt`-t adja vissza a `foo10.txt` előtt.

A Finder lehetővé teszi a rendezést saját funkcióval is. Paraméterként két `Nette\Utils\FileInfo` objektumot kap, és vissza kell adnia az `<=>` operátorral végzett összehasonlítás eredményét, azaz `-1`, `0` vagy `1`. Például így rendezzük a fájlokat méret szerint:

```php
$finder->sortBy(fn($a, $b) => $a->getSize() <=> $b->getSize());
```


Több különböző keresés
----------------------

Ha több különböző fájlt kell találnia különböző helyeken, vagy más kritériumoknak megfelelőket, használja az `append()` metódust. Új `Finder` objektumot ad vissza, így lehetséges a metódushívásokat láncolni:


```php
($finder = new Finder) // a $finder változóba elmentjük az első Findert!
	->files('*.php')   // a src/-ben *.php fájlokat keresünk
	->from('src')
	->append()
	->files('*.md')    // a docs/-ban *.md fájlokat keresünk
	->from('docs')
	->append()
	->files('*.json'); // az aktuális mappában *.json fájlokat keresünk
```

Alternatívaként használható az `append()` metódus egy konkrét fájl (vagy fájlok tömbjének) hozzáadására. Akkor ugyanazt a `Finder` objektumot adja vissza:

```php
$finder = Finder::findFiles('*.txt')
	->append(__FILE__);
```


FileInfo
--------

A [Nette\Utils\FileInfo |api:] egy fájlt vagy könyvtárat reprezentáló osztály a keresési eredményekben. Ez a [SplFileInfo |php:SplFileInfo] osztály kiterjesztése, amely információkat nyújt, mint például a fájlméret, utolsó módosítás dátuma, név, elérési út, stb.

Ezenkívül metódusokat biztosít a relatív elérési út visszaadására, ami hasznos a mélységi bejárás során:

```php
foreach (Finder::findFiles('*.jpg')->from('.') as $file) {
	$absoluteFilePath = $file->getRealPath();
	$relativeFilePath = $file->getRelativePathname();
}
```

Továbbá rendelkezésre állnak metódusok a fájl tartalmának olvasására és írására:

```php
foreach ($finder as $file) {
    $contents = $file->read();
    // ...
    $file->write($contents);
}
```


Eredmények visszaadása tömbként
-------------------------------

Ahogy a példákban látható volt, a Finder implementálja az `IteratorAggregate` interfészt, így használhatja a `foreach`-et az eredmények bejárására. Úgy van programozva, hogy az eredmények csak a bejárás során töltődnek be, így ha nagy mennyiségű fájlja van, nem várja meg, amíg mind beolvasódik.

Az eredményeket `Nette\Utils\FileInfo` objektumok tömbjeként is visszaadhatja, méghozzá a `collect()` metódussal. A tömb nem asszociatív, hanem numerikus.

```php
$array = $finder->findFiles('*.php')->collect();
```

Finder: fájlok keresése

Olyan fájlokat kell találnia, amelyek megfelelnek egy adott maszknak? A Finder segít ebben. Ez egy sokoldalú és gyors eszköz a könyvtárstruktúra bejárására.

Telepítés:

composer require nette/utils

A példák feltételezik a következő alias létrehozását:

use Nette\Utils\Finder;

Használat

Először megmutatjuk, hogyan írhatja ki a .txt és .md kiterjesztésű fájlneveket az aktuális könyvtárban a Nette\Utils\Finder segítségével:

foreach (Finder::findFiles(['*.txt', '*.md']) as $name => $file) {
	echo $file;
}

A keresés alapértelmezett könyvtára az aktuális könyvtár, de ezt megváltoztathatja az in() vagy from() metódusokkal. A $file változó a FileInfo osztály példánya, rengeteg hasznos metódussal. A $name kulcsban a fájl elérési útja található stringként.

Mit kell keresni?

A findFiles() metódus mellett létezik a findDirectories(), amely csak könyvtárakat keres, és a find(), amely mindkettőt keresi. Ezek a metódusok statikusak, így példány létrehozása nélkül hívhatók. A maszk paraméter opcionális, ha nem adja meg, mindent megkeres.

foreach (Finder::find() as $file) {
	echo $file; // most minden fájl és könyvtár kiíródik
}

A files() és directories() metódusokkal kiegészítheti, hogy mi mást kell keresni. A metódusok ismételten hívhatók, és paraméterként maszkok tömbje is megadható:

Finder::findDirectories('vendor') // minden könyvtár
	->files(['*.php', '*.phpt']); // plusz minden PHP fájl

A statikus metódusok alternatívája a példány létrehozása a new Finder segítségével (az így létrehozott friss objektum semmit sem keres), és a files() és directories() segítségével megadni, mit kell keresni:

(new Finder)
	->directories()      // minden könyvtár
	->files('*.php');    // plusz minden PHP fájl

A maszkban használhat helyettesítő karaktereket *, **, ? és [...]. Akár könyvtárakat is megadhat, például a src/*.php megkeresi az összes PHP fájlt a src könyvtárban.

A szimbolikus linkek szintén könyvtárnak vagy fájlnak minősülnek.

Hol kell keresni?

A keresés alapértelmezett könyvtára az aktuális könyvtár. Ezt az in() és from() metódusokkal változtathatja meg. Ahogy a metódusnevekből is látható, az in() csak az adott könyvtárban keres, míg a from() annak alkönyvtáraiban is keres (rekurzívan). Ha rekurzívan szeretne keresni az aktuális könyvtárban, használhatja a from('.')-ot.

Ezek a metódusok többször is hívhatók, vagy több elérési utat átadhat nekik tömbként, a fájlok ezután minden könyvtárban keresve lesznek. Ha valamelyik könyvtár nem létezik, Nette\UnexpectedValueException kivétel dobódik.

Finder::findFiles('*.php')
	->in(['src', 'tests']) // közvetlenül keres a src/ és tests/ könyvtárakban
	->from('vendor');      // a vendor/ alkönyvtáraiban is keres

A relatív elérési utak az aktuális könyvtárhoz képest relatívak. Természetesen abszolút elérési utakat is meg lehet adni:

Finder::findFiles('*.php')
	->in('/var/www/html');

Az elérési úton lehet használni helyettesítő karaktereket *, **, ?. Így például a src/*/*.php elérési út segítségével keresheti az összes PHP fájlt a src könyvtár második szintű könyvtáraiban. A ** karakter, amit globstarnak neveznek, egy erős aduász, mert lehetővé teszi az alkönyvtárakban való keresést is: a src/**/tests/*.php segítségével keresi az összes PHP fájlt a tests könyvtárban, amely a src-ben vagy annak bármely alkönyvtárában található.

Ellenben a [...] helyettesítő karakterek az elérési úton nem támogatottak, azaz nincs különleges jelentésük, hogy elkerüljük a nem kívánt viselkedést abban az esetben, ha például az in(__DIR__)-t keresi, és véletlenül az elérési úton [] karakterek lesznek.

Fájlok és könyvtárak mélységi keresésekor először a szülőkönyvtárat adja vissza, csak azután a benne lévő fájlokat, amit a childFirst() segítségével meg lehet fordítani.

Helyettesítő karakterek

A maszkban több speciális karaktert használhat:

  • * – tetszőleges számú tetszőleges karaktert helyettesít (kivéve /)
  • ** – tetszőleges számú tetszőleges karaktert helyettesít, beleértve a /-t is (azaz többszintű keresés lehetséges)
  • ? – egy tetszőleges karaktert helyettesít (kivéve /)
  • [a-z] – egy karaktert helyettesít a szögletes zárójelben lévő karakterlistából
  • [!a-z] – egy karaktert helyettesít a szögletes zárójelben lévő karakterlistán kívül

Használati példák:

  • img/?.png – egybetűs nevű fájlok 0.png, 1.png, x.png, stb.
  • logs/[0-9][0-9][0-9][0-9]-[01][0-9]-[0-3][0-9].log – YYYY-MM-DD formátumú naplók
  • src/**/tests/* – fájlok a src/tests, src/foo/tests, src/foo/bar/tests könyvtárakban és így tovább.
  • docs/**.md – minden .md kiterjesztésű fájl a docs könyvtár összes alkönyvtárában

Kizárás

Az exclude() metódussal kizárhat fájlokat és könyvtárakat a keresésből. Megadja a maszkot, amelynek a fájl nem felelhet meg. Példa *.txt fájlok keresésére, kivéve azokat, amelyek nevében X betű szerepel:

Finder::findFiles('*.txt')
	->exclude('*X*');

A bejárt alkönyvtárak kihagyásához használja az exclude()-ot:

Finder::findFiles('*.php')
	->from($dir)
	->exclude('temp', '.git')

Szűrés

A Finder több metódust kínál az eredmények szűrésére (azaz azok csökkentésére). Kombinálhatja őket és ismételten hívhatja.

A size() segítségével fájlméret szerint szűrünk. Így találunk 100 és 200 bájt közötti méretű fájlokat:

Finder::findFiles('*.php')
	->size('>=', 100)
	->size('<=', 200);

A date() metódus a fájl utolsó módosításának dátuma szerint szűr. Az értékek lehetnek abszolútak vagy relatívak az aktuális dátumhoz és időhöz képest, például így találjuk meg az elmúlt két hétben módosított fájlokat:

Finder::findFiles('*.php')
	->date('>', '-2 weeks')
	->from($dir)

Mindkét funkció érti a >, >=, <, <=, =, !=, <> operátorokat.

A Finder lehetővé teszi az eredmények szűrését saját funkciók segítségével is. A funkció paraméterként kap egy Nette\Utils\FileInfo objektumot, és true-t kell visszaadnia, hogy a fájl bekerüljön az eredmények közé.

Példa: olyan PHP fájlok keresése, amelyek tartalmazzák a Nette stringet (kis- és nagybetűk figyelmen kívül hagyásával):

Finder::findFiles('*.php')
	->filter(fn($file) => strcasecmp($file->read(), 'Nette') === 0);

Mélységi szűrés

Rekurzív kereséskor beállíthatja a maximális bejárási mélységet a limitDepth() metódussal. Ha beállítja a limitDepth(1)-et, csak az első alkönyvtárakat járja be, a limitDepth(0) kikapcsolja a mélységi bejárást, és a –1 érték törli a korlátot.

A Finder lehetővé teszi saját funkciókkal eldönteni, melyik könyvtárba lépjen be a bejárás során. A funkció paraméterként kap egy Nette\Utils\FileInfo objektumot, és true-t kell visszaadnia, hogy belépjen a könyvtárba:

Finder::findFiles('*.php')
	->descentFilter(fn($file) => $file->getBasename() !== 'temp');

Rendezés

A Finder több funkciót is kínál az eredmények rendezésére.

A sortByName() metódus az eredményeket fájlnevek szerint rendezi. A rendezés naturális, azaz helyesen kezeli a számokat a nevekben, és például a foo1.txt-t adja vissza a foo10.txt előtt.

A Finder lehetővé teszi a rendezést saját funkcióval is. Paraméterként két Nette\Utils\FileInfo objektumot kap, és vissza kell adnia az <=> operátorral végzett összehasonlítás eredményét, azaz -1, 0 vagy 1. Például így rendezzük a fájlokat méret szerint:

$finder->sortBy(fn($a, $b) => $a->getSize() <=> $b->getSize());

Több különböző keresés

Ha több különböző fájlt kell találnia különböző helyeken, vagy más kritériumoknak megfelelőket, használja az append() metódust. Új Finder objektumot ad vissza, így lehetséges a metódushívásokat láncolni:

($finder = new Finder) // a $finder változóba elmentjük az első Findert!
	->files('*.php')   // a src/-ben *.php fájlokat keresünk
	->from('src')
	->append()
	->files('*.md')    // a docs/-ban *.md fájlokat keresünk
	->from('docs')
	->append()
	->files('*.json'); // az aktuális mappában *.json fájlokat keresünk

Alternatívaként használható az append() metódus egy konkrét fájl (vagy fájlok tömbjének) hozzáadására. Akkor ugyanazt a Finder objektumot adja vissza:

$finder = Finder::findFiles('*.txt')
	->append(__FILE__);

FileInfo

Nette\Utils\FileInfo egy fájlt vagy könyvtárat reprezentáló osztály a keresési eredményekben. Ez a SplFileInfo osztály kiterjesztése, amely információkat nyújt, mint például a fájlméret, utolsó módosítás dátuma, név, elérési út, stb.

Ezenkívül metódusokat biztosít a relatív elérési út visszaadására, ami hasznos a mélységi bejárás során:

foreach (Finder::findFiles('*.jpg')->from('.') as $file) {
	$absoluteFilePath = $file->getRealPath();
	$relativeFilePath = $file->getRelativePathname();
}

Továbbá rendelkezésre állnak metódusok a fájl tartalmának olvasására és írására:

foreach ($finder as $file) {
    $contents = $file->read();
    // ...
    $file->write($contents);
}

Eredmények visszaadása tömbként

Ahogy a példákban látható volt, a Finder implementálja az IteratorAggregate interfészt, így használhatja a foreach-et az eredmények bejárására. Úgy van programozva, hogy az eredmények csak a bejárás során töltődnek be, így ha nagy mennyiségű fájlja van, nem várja meg, amíg mind beolvasódik.

Az eredményeket Nette\Utils\FileInfo objektumok tömbjeként is visszaadhatja, méghozzá a collect() metódussal. A tömb nem asszociatív, hanem numerikus.

$array = $finder->findFiles('*.php')->collect();