kcs/class-finder
Discover and filter PHP classes and namespaces in your project using Composer’s autoloader with PSR resolution. Iterate found classes and reflections, then narrow results by interfaces, subclasses, annotations, PHP 8 attributes, directories, namespaces, or custom callbacks.
kcs/class-finder package provides utility classes for dynamic class/namespace discovery, which is valuable in Laravel for:
Illuminate\Support\ServiceProvider::boot() or Illuminate\Foundation\Application::register()).ClassFinder (e.g., Illuminate\Filesystem\Filesystem::glob()) or Composer’s autoloader, but offers higher-level abstractions (e.g., filtering by traits, interfaces, or annotations).Stringable, Attribute support). Works seamlessly with Laravel 10+.SplFileInfo and ReflectionClass, which are CPU-intensive for large codebases. Benchmark against Laravel’s native glob() or spatie/laravel-package-tools.| Risk Area | Severity | Mitigation |
|---|---|---|
| False Positives/Negatives | High | Validate against Laravel’s app_path(), config_path(), etc., to avoid scanning vendor/node_modules. |
| Recursive Scanning | Medium | Limit depth or use Filesystem::allFiles() for safer traversal. |
| Reflection Overhead | Medium | Cache results (e.g., via Illuminate\Support\Facades\Cache) for repeated calls. |
| Annotation Parsing | Low | Only use if leveraging Attribute (PHP 8+) or a third-party parser like phpDocumentor. |
| Laravel-Specific Quirks | Low | Test with Laravel’s bootstrap/app.php and config/app.php overrides. |
Why not use Laravel’s native tools?
glob()?App\Modules\* that implement ShouldRegister::class."Performance Trade-offs
Maintenance Burden
AppServiceProvider)?Testing Strategy
Future-Proofing
never return types)?Illuminate\Contracts integration)?bind()/singleton() calls with dynamic discovery (e.g., auto-register all *Service classes in app/Modules/).Console/Kernel.php edits.vendor/package/src/ for *ServiceProvider classes).spatie/laravel-package-tools for package bootstrapping.nunomaduro/collision for conflict detection during discovery.| Phase | Action | Tools/Leverage |
|---|---|---|
| Assessment | Audit current discovery logic (e.g., AppServiceProvider, config/app.php). |
php artisan package:discover (Laravel) |
| Pilot | Replace one manual registration (e.g., commands) with dynamic discovery. | ClassFinder::findClasses() + Reflection |
| Validation | Test with CI/CD (e.g., GitHub Actions) to ensure no regressions. | pest or phpunit |
| Rollout | Gradually migrate other areas (e.g., event listeners, middleware). | Feature flags (Laravel Nova/Forge) |
| Optimization | Cache results or lazy-load discovery. | Illuminate\Support\Facades\Cache |
Stringable).composer dump-autoload is run post-installation.storage/, app/).Pre-Integration:
composer.json:
"require": {
"alekitto/class-finder": "^1.0"
}
composer install --optimize-autoloader.Discovery Implementation:
AppServiceProvider:
use Alekitto\ClassFinder\ClassFinder;
public function boot()
{
$commands = ClassFinder::findClasses(
app_path('Console/Commands'),
['*Command']
)->map(fn ($class) => new $class);
$this->commands($commands);
}
Post-Integration:
ClassFinder).App\Services\*").bind() calls or config/app.php edits.AppServiceProvider).ClassFinder::findClasses()->each(fn ($class) => \Log::debug("Discovered: $class"));
assert() or custom exceptions for critical classes.App\Modules\* are scanned").## Class Discovery
Classes are discovered recursively from `app/Modules/`. To exclude a directory:
```php
ClassFinder::exclude('app/Modules/Deprecated');
vendor/).new ReflectionClass() is expensive.vendor/):
$classes = Cache::remember('discovered_classes', now()->addHours(1), function () {
return ClassFinder::findClasses(app_path('Modules'));
});
spatie/async to scan directories concurrently.How can I help you explore Laravel packages today?