phpdocumentor/flyfinder
FlyFinder is a utility for Flysystem that finds files by criteria such as hidden status, extension, or path, with wildcard path support. It returns files only, not directories, and integrates easily via Composer.
IsHidden, HasExtension, InPath, Glob, plus and/or/not combinators). The build alternative is 100–200 lines of RecursiveDirectoryIterator glue plus per-adapter special-casing. The buy cost is one MIT dependency, so this is a low-stakes decision best made on fit, not on cost.Filesystem, so the same query returns the same results over local disks, in-memory adapters, S3, or SFTP. This matters if your roadmap includes remote or pluggable storage: a hand-rolled local-only walker becomes a rewrite the day a non-local adapter appears.InPath/Glob) are exactly the controls used to avoid scanning .git/node_modules, avoid publishing dotfiles, or restrict a scan to an allowlisted subtree. Encoding these as named specifications makes the policy readable and testable rather than buried in an if ladder.Consider adopting when:
andSpecification / orSpecification / notSpecification) rather than bespoke.^2.0.1 (2.0.1 fixed a Glob defect that could write into Flysystem 3 attributes — a data-integrity concern if you are on 2.0.0), and add a smoke test around Glob against a real disk.Look elsewhere or build in-house when:
glob()/RecursiveDirectoryIterator or Symfony Finder covers this with a far larger user base, more documentation, and no additional dependency. Symfony Finder is the default answer unless remote/multi-adapter storage is on the table.Decision rule: adopt if Flysystem 3 is already in the stack and you need composable, adapter-agnostic file queries. Otherwise, use Symfony Finder or native iteration and revisit only when a second storage backend appears.
To executives: "We have a recurring, low-glamour engineering task: finding the right files inside a storage location so a feature can act on them. Today each team writes that scan themselves, slightly differently, and it breaks when storage changes. FlyFinder is a small, MIT-licensed, zero-cost library that standardizes that step. It carries no license fee, no runtime service, and no vendor relationship, and its blast radius is contained because we will wrap it behind our own interface. Expected value is measured in days of engineering saved per integration and in avoided rework if we add remote storage — not in new customer-facing capability. The risk is maintenance, not functionality: the project is small and single-maintainer, so we adopt it with a pinned version and a documented exit path rather than as a foundational dependency."
To engineering:
composer require phpdocumentor/flyfinder:^2.0.1 — pin at or above 2.0.1; 2.0.0 had a Glob bug that wrote into Flysystem 3 attributes.Finder with an existing Flysystem Filesystem, then compose specifications — $inPath->andSpecification($hasExtension)->andSpecification($isHidden->notSpecification()). InPath accepts wildcards; Glob gives more flexible matching.composer.json against our Laravel version before adoption — that compatibility check, not learning the API, is the real ramp-up cost (under a day either way).Glob against a real disk, and benchmark once against your largest expected tree or any remote adapter before putting it on a hot path.How can I help you explore Laravel packages today?