spatie/php-structure-discoverer
Automatically discover classes, interfaces, traits, and other PHP structures in a codebase. Scans files, resolves namespaces, and returns a structured overview you can use for tooling, analysis, or building package features without manual registration.
Start by installing the package via Composer: composer require spatie/php-structure-discoverer. The primary entry point is the StructureDiscoverer class—use it to scan a directory and retrieve discovered structures. A minimal first use case is listing all classes in your project:
use Spatie\StructureDiscoverer\Facades\StructureDiscoverer;
$structures = StructureDiscoverer::discover(__DIR__ . '/app');
foreach ($structures->getClasses() as $class) {
echo $class->getFqn() . PHP_EOL; // e.g., "App\Models\User"
}
Check the README.md and src/Facades/StructureDiscoverer.php first—they contain the core API surface. The discover() method returns a StructureCollection, which offers methods like getInterfaces(), getTraits(), and getEnums(), along with filter() and map() for further processing.
The package shines in tooling that requires structured introspection. Common patterns include:
Architecture Linting: Enforce naming conventions or structural rules (e.g., “All services must be in App\Services\* and implement ServiceInterface”).
$services = StructureDiscoverer::discover('app/Services')
->getClasses()
->filter(fn($class) => !$class->getInterfaces()->contains('ServiceInterface'));
Documentation Generation: Populate changelogs or API docs by scanning classes and extracting annotations or docblocks via $class->getMethods() and $method->getDocBlock().
Dependency Mapping: Build dependency graphs by analyzing method signatures or type hints (e.g., resolve which services inject which repositories).
Custom Analyzers: Combine with php-parser-based tools for deeper static analysis. The Discoverer handles what exists, your code handles what it means.
Use StructureDiscoverer::forFiles([...]) for fine-grained control over individual file inclusion, or withFilters([...]) to exclude tests/, stubs/, or vendor folders globally.
Scanner Reliability: It uses PHP’s token_get_all() internally, so it cannot discover structures in files with syntax errors. Always lint your codebase first if results are inconsistent.
Incomplete Method Details: While method names, visibilities, and docblocks are surfaced, parameter types (except for scalar hints) and return types require PHP 7.0+ reflection, which the discoverer does not rely on. For type-accurate analysis, combine with nikic/php-parser.
Lazy Collection Gotcha: StructureCollection is a LazyCollection—calling toArray() or all() triggers full traversal. For large codebases, prefer streaming with each() to avoid memory spikes.
Extensibility: Extend Discoverer or implement custom filters via DiscoverFilter to handle language features like PHP 8 attributes (#[Attribute]) or named arguments.
Caching Tip: For CLI tools, cache discovery results using StructureDiscoverer::cached(...)—it saves ~100–300ms per run in medium projects by serializing to storage_path('structure-discoverer-cache.json').
Namespace Collisions: If your codebase uses aliasing (use statements), the discoverer reports fully qualified names only—no alias resolution is done. Use $class->getUseStatements() if alias mapping is needed.
How can I help you explore Laravel packages today?