Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Finder Facade Laravel Package

sebastian/finder-facade

A convenience wrapper around Symfony Finder that simplifies locating files in PHP projects. It provides a fluent, facade-style API for common search patterns, filtering, and exclusions, making file discovery easier for tools such as PHPUnit and code coverage.

View on GitHub
Deep Wiki
Context7

Getting Started

sebastian/finder-facade is a tiny wrapper around symfony/finder that collapses the common “find files by path, name, and exclusion list” setup into one constructor plus findFiles(). It is archived and unmaintained, so treat it as a convenience for existing code, not a new strategic dependency.

Install it (dev-only is usually appropriate):

composer require --dev sebastian/finder-facade
composer show sebastian/finder-facade

Look first at vendor/sebastian/finder-facade/src/FinderFacade.php. It is a single, short class — reading it takes a minute and tells you exactly which Finder defaults are applied. The README is minimal; the source is the real documentation.

Public API shape:

use SebastianBergmann\FinderFacade\FinderFacade;

$facade = new FinderFacade(
    [app_path()],          // paths to search
    ['*.php'],             // file name patterns
    ['Console/Kernel.php'] // exclusions
);

$files = $facade->findFiles(); // array of Symfony\Component\Finder\SplFileInfo

A good first use case is an Artisan command that lists candidate PHP files for an audit, code-generation step, or static-analysis pass:

$files = (new FinderFacade(
    [app_path()],
    ['*.php'],
    ['Console/Kernel.php', 'vendor']
))->findFiles();

foreach ($files as $file) {
    $this->line($file->getRealPath());
}

Older releases may expose a findFiles(true) mode that returns path strings; check the installed version before relying on it. In current usage, expect SplFileInfo objects and call getRealPath() or getPathname() yourself.

Implementation Patterns

Wrap it in a small application service. Avoid scattering FinderFacade construction through commands and jobs. A scanner service gives you one place to normalize paths, sort results, and handle missing directories.

namespace App\Support;

use SebastianBergmann\FinderFacade\FinderFacade;

final class PhpFileScanner
{
    /** @return list<string> */
    public function scan(
        array $paths,
        array $names = ['*.php'],
        array $exclude = []
    ): array {
        return collect((new FinderFacade($paths, $names, $exclude))->findFiles())
            ->map(fn ($file) => $file->getRealPath())
            ->sort()
            ->values()
            ->all();
    }
}

Bind it as a singleton in a service provider if you want to inject it into commands, jobs, or other services:

$this->app->singleton(\App\Support\PhpFileScanner::class);

Drive it from config, not hard-coded paths. A config/scanner.php file keeps environment-specific exclusions out of the command:

return [
    'paths' => [app_path(), database_path('migrations')],
    'names' => ['*.php'],
    'exclude' => ['vendor', 'node_modules', 'storage'],
];

Then combine config defaults with CLI overrides:

$paths = $this->option('path') ?: config('scanner.paths');
$names = $this->option('name') ?: config('scanner.names');
$exclude = $this->option('exclude') ?: config('scanner.exclude');

Use it for discovery, then hand off to Laravel for content. The facade only finds files. Use File::get(), SplFileInfo::getContents(), or token_get_all() once you have the list. Typical day-to-day uses in a Laravel app:

  • Finding all PHP classes under app/ to build a class map or registration list.
  • Scanning migrations for a custom migrate:status-style report.
  • Collecting Blade components or Livewire components for documentation generation.
  • Finding test files for a custom test-runner or CI reporting command.
  • Locating files for TODO/FIXME audits or coding-standard checks.
  • Feeding a code generator that scaffolds files based on existing classes.

Make output deterministic. Finder does not promise a stable order, and filesystem order varies between machines. Always sort() or use Symfony Finder’s sortByName() directly if the order matters for diffs, snapshots, or generated documentation.

Test with real fixture directories. A tests/Fixtures/scanner/ tree works well. Laravel’s Storage::fake() uses Flysystem and is invisible to Symfony Finder, so it is the wrong tool here.

Know when to drop the wrapper. If you need ignoreDotFiles(false), followLinks(), depth(), date(), sortByName(), or streaming iteration, use Symfony\Component\Finder\Finder directly. The facade is deliberately narrow and exposes no extension hooks beyond subclassing or copying the class.

Gotchas and Tips

  • Archived and unmaintained. New Laravel projects should generally use symfony/finder directly. The facade adds almost no behavior beyond defaulting to files, ignoring VCS directories, and applying names/exclusions. Migrating is usually a five-line change.
  • No Laravel integration. There is no service provider, facade alias, config file, or publishable asset. Composer auto-discovery does nothing for this package.
  • findFiles() is eager. It returns a full array, so very large directory trees consume memory. For big repositories, use Symfony Finder’s iterator or add chunking around the results.
  • Existence is checked late. A nonexistent path is not rejected in the constructor; Symfony Finder throws DirectoryNotFoundException when iteration begins. Wrap scans in a try/catch and validate paths with is_dir() before presenting user-supplied options.
  • Unreadable directories can throw. Symfony Finder’s default does not ignore unreadable directories, so permission problems can surface as AccessDeniedException. This matters when scanning mounted volumes, node_modules, or shared hosting directories.
  • Hidden files are invisible by default. The facade does not expose ignoreDotFiles(false). If you need .env.example, .github workflows, or other dotfiles, use Finder directly.
  • Symlinks are not followed by default. The facade also does not expose followLinks(). Symlinked packages or deployment layouts may appear empty.
  • Exclusions are path-based, not “skip this directory” magic. Verify whether your version passes exclusions to notPath() or exclude() in Symfony Finder; semantics differ, and patterns are relative to each in() root. Test exclusions explicitly rather than assuming vendor behaves like a global ignore.
  • Use absolute paths. In queue workers, Octane, and scheduler contexts, the current working directory may not be what you expect. Always pass base_path(), app_path(), database_path(), etc.
  • Do not confuse it with Laravel’s filesystem helpers. Illuminate\Filesystem\Filesystem::allFiles() is fine for simple recursive listing, but it lacks name-pattern and exclusion filtering. Symfony Finder is the closer replacement.
  • Watch Composer constraints. Because the package is archived, its symfony/finder constraint may lag behind the Symfony major version used by your Laravel release. Run composer why symfony/finder and composer why-not sebastian/finder-facade when resolution fails.
  • License metadata is ambiguous. GitHub reports NOASSERTION; check the repository LICENSE file before redistributing or bundling. Sebastian Bergmann packages are typically BSD-3-Clause, but verify rather than assume.
  • Debugging tip. Since findFiles() returns an array, inspect it directly in Tinker or a command with dump(array_map(fn ($f) => $f->getRealPath(), $files)). If the list is empty, check path existence, dotfile handling, name patterns, and exclusions in that order.
  • Case sensitivity and glob semantics differ by platform. *.PHP may match on macOS but not Linux. Prefer lowercase extensions in patterns and test in the same environment as production.
  • Best extension point is replacement. If you need more Finder behavior, copy the short FinderFacade class into your app and adapt it, or use Symfony Finder directly. Subclassing gives you little because the Finder instance is created internally and not exposed.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
shitoudev/permissionmanager
johannesclimacus/laravel-tui
hocvt/seotools
vitalybaev/sypexgeo
amphibee/themosis-ignition
gito-me/fast-excel
frankyso/laravel-ipaymu
geolize-studio/laravel-chile
boomerangui/chat
jinas/dhivatar
store-doc/laravel-storage-driver
plus-it/laravel-translation-manager
diephp/perhaps
diephp/telegraph
osmaviation/spreadsheet
microsoft/fluentui-system-icons
mmccook/php-json-canonicalization-scheme
middlewares/firewall
qubiqx/montapacking
nyoncode/laravel-package-console