Weave Code
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

Class Finder Laravel Package

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.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation Add the package via Composer:

    composer require alekitto/class-finder
    

    No additional configuration is required—it’s a drop-in utility.

  2. First Use Case: Finding Classes in a Namespace Locate all classes under App\Models:

    use Alekitto\ClassFinder\ClassFinder;
    
    $finder = new ClassFinder();
    $classes = $finder->findClassesInNamespace('App\Models');
    
    foreach ($classes as $class) {
        echo $class . "\n";
    }
    
  3. Key Entry Points

    • ClassFinder::findClassesInNamespace(string $namespace) – Recursively scans a namespace.
    • ClassFinder::findClassesByTrait(string $trait) – Finds classes using a specific trait.
    • ClassFinder::findClassesByInterface(string $interface) – Finds classes implementing an interface.
    • ClassFinder::findClassesUsingMethod(string $method) – Finds classes with a given method signature.

Implementation Patterns

Common Workflows

1. Dynamic Service Discovery

Useful for auto-registering services (e.g., event listeners, commands):

$listeners = (new ClassFinder())
    ->findClassesUsingMethod('handle')
    ->filter(fn($class) => class_implements($class, EventListener::class));

foreach ($listeners as $listener) {
    app()->bindEventListener($listener);
}

2. Testing Utilities

Generate test stubs for all classes in a module:

$moduleClasses = (new ClassFinder())
    ->findClassesInNamespace('App\Modules\Auth')
    ->filter(fn($class) => !str_contains($class, 'Test'));

foreach ($moduleClasses as $class) {
    $testClass = str_replace('\\', '\\Tests\\', $class) . 'Test';
    // Generate test stub...
}

3. Code Analysis Tools

Audit classes for deprecated methods:

$classesWithDeprecated = (new ClassFinder())
    ->findClassesInNamespace('App')
    ->filter(fn($class) => method_exists($class, 'deprecatedMethod'));

4. Integration with Laravel’s Service Provider

Bootstrapping in AppServiceProvider:

public function boot()
{
    $this->registerDynamicCommands();
}

protected function registerDynamicCommands()
{
    $commands = (new ClassFinder())
        ->findClassesUsingMethod('handle')
        ->filter(fn($class) => is_subclass_of($class, Command::class));

    foreach ($commands as $command) {
        $this->commands($command);
    }
}

Integration Tips

  1. Caching Results Cache results for performance-critical paths (e.g., service registration):

    $classes = Cache::remember('namespace_classes', now()->addHours(1), function() {
        return (new ClassFinder())->findClassesInNamespace('App\Services');
    });
    
  2. Combining with Reflection Use ReflectionClass for deeper introspection:

    $reflection = new ReflectionClass($class);
    $methods = $reflection->getMethods();
    
  3. Excluding Directories Skip Tests, Migrations, or Vendor folders:

    $finder = new ClassFinder();
    $finder->excludeDirectories(['Tests', 'Migrations']);
    $classes = $finder->findClassesInNamespace('App');
    
  4. Leveraging with Laravel’s Facades Integrate with app() for dependency injection:

    $finder = app(ClassFinder::class);
    

Gotchas and Tips

Pitfalls

  1. Performance with Large Codebases

    • Issue: Recursive scans can be slow for monorepos or deeply nested namespaces.
    • Fix: Cache results aggressively or limit search depth:
      $finder->setMaxDepth(3); // Limit to 3 levels deep
      
  2. False Positives in Trait/Interface Detection

    • Issue: findClassesByTrait may include classes that use the trait indirectly (e.g., via inheritance).
    • Fix: Combine with class_uses() for stricter checks:
      $classes = (new ClassFinder())->findClassesByTrait('Serializable');
      $classes = array_filter($classes, fn($class) => in_array('Serializable', class_uses($class)));
      
  3. Namespace Pollution

    • Issue: Accidental inclusion of classes from vendor/ or node_modules/.
    • Fix: Explicitly exclude vendor directories:
      $finder->excludeDirectories(['vendor', 'node_modules']);
      
  4. Static Analysis Limitations

    • Issue: Won’t detect dynamically generated classes (e.g., via eval() or create_function).
    • Workaround: Supplement with runtime checks if needed.

Debugging Tips

  1. Enable Verbose Output Temporarily enable debug mode to see scanned files:

    $finder->setDebug(true);
    $classes = $finder->findClassesInNamespace('App');
    
  2. Validate Results Cross-check with get_declared_classes() for edge cases:

    $declared = get_declared_classes();
    $found = (new ClassFinder())->findClassesInNamespace('App');
    $missing = array_diff($declared, $found);
    
  3. Handle Autoloading Issues If classes are missing, ensure Composer’s autoloader is up-to-date:

    composer dump-autoload
    

Extension Points

  1. Custom Filters Extend with anonymous functions or callables:

    $finder = new ClassFinder();
    $finder->addFilter(fn($class) => str_contains($class, 'Service'));
    
  2. Post-Processing Hooks Override ClassFinder::processClass() to modify results:

    class CustomFinder extends ClassFinder {
        protected function processClass(string $class): bool {
            return parent::processClass($class) && !str_ends_with($class, 'Builder');
        }
    }
    
  3. Integration with Laravel’s Events Trigger events when classes are discovered:

    $finder = new ClassFinder();
    $finder->on('class_found', fn($class) => Log::debug("Found: {$class}"));
    $finder->findClassesInNamespace('App');
    
  4. Parallel Processing For large scans, use Laravel’s queues or parallel processing:

    $classes = (new ClassFinder())->findClassesInNamespace('App');
    dispatch(fn() => processClasses($classes))->onQueue('class-discovery');
    
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.
terminal42/code-quality-tools
codifyo/ts-generator-bundle
testo/fiber
mintobit/jobqueue
a4sex/maintenance-bundle
a4sex/entity-date-update
a4sex/client-identifier
a4sex/base-utilites
a4sex/key-value-storage
a4sex/micro-status
chilldev/dependency-injection-extra
datinglibre/datinglibre-app-api
biberltd/corebundle
bricre/symfony-bundle-test
biberltd/logbundle
dominium/http-adapter-bundle
dominium/google-analytics
a4sex/auto-clean-entity
christhompsontldr/laravel-inky
spatie/mailcoach-vapor