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

Laravel Auto Discoverer Laravel Package

spatie/laravel-auto-discoverer

Fast, cached discovery of PHP classes, interfaces, traits, and enums based on conditions. Scan directories to find structures implementing an interface, using attributes, extending classes, and more—ideal for auto-registration and production-ready performance.

View on GitHub
Deep Wiki
Context7

Technical Evaluation

Architecture Fit

  • Use Case Alignment: The package excels in scenarios requiring dynamic class/interface/trait discovery (e.g., plugin systems, dynamic service registration, or framework-agnostic dependency resolution). It’s particularly valuable in modular Laravel applications where components are auto-loaded or where runtime reflection is needed (e.g., event listeners, middleware, or policy resolution).
  • Laravel Synergy: While not Laravel-specific, it integrates seamlessly with Laravel’s service provider bootstrapping, facade resolution, and dynamic binding systems. For example, it could replace manual app()->bind() calls for interfaces with auto-discovered implementations.
  • Alternatives: Could complement or replace partial solutions like:
    • Laravel’s built-in ClassLoader (limited to PSR-4).
    • Custom ReflectionClass loops (verbose, no caching).
    • laravel-discoverable-policies (niche use case).

Integration Feasibility

  • Low Friction: Designed for zero-config use in PHP 8.1+ (Laravel 9+). The Discover facade provides a fluent API, reducing boilerplate.
  • Cache Layer: Built-in caching (via Discover::cache()) mitigates performance overhead in large codebases, critical for runtime discovery (e.g., plugin systems).
  • Extensibility: Supports custom predicates (e.g., hasMethod(), usesTrait()), enabling advanced filtering (e.g., "find all classes extending BaseController with a handle() method").

Technical Risk

  • False Positives/Negatives: Misconfigured predicates (e.g., implementing()) could return incorrect results. Mitigate via unit tests with edge cases (e.g., abstract classes, anonymous classes).
  • Cache Invalidation: Manual cache clearing (Discover::clearCache()) may be needed post-deployment. Automate via Laravel’s cache:clear or config:clear hooks.
  • PHP Version: Requires PHP 8.1+ (Laravel 9+). Risk: Legacy apps may need upgrades or polyfills (e.g., for enum support).
  • Performance: Uncached discovery on large codebases (10K+ classes) could introduce latency. Mitigation: Pre-warm cache during bootstrap/app.php or use Discover::cacheForMinutes(1440).

Key Questions

  1. Discovery Scope: Should discovery be global (entire app/ dir) or scoped (e.g., app/Modules/*)? Scoping reduces noise but requires explicit path configuration.
  2. Cache Strategy: Should cache be persistent (file/database) or in-memory (Redis)? Persistent cache survives deployments but adds complexity.
  3. Dynamic vs. Static: Is discovery runtime-only (e.g., plugins) or compile-time (e.g., generating config files)? Compile-time enables optimizations (e.g., pre-resolving dependencies).
  4. Error Handling: How should invalid classes (e.g., missing files) be handled? Return empty results, throw exceptions, or log warnings?
  5. Testing: How will discovery results be validated in CI? Mock Discover or use a golden file of expected outputs?

Integration Approach

Stack Fit

  • Laravel Ecosystem:
    • Service Providers: Replace manual bind() calls with auto-discovered implementations (e.g., Discover::in(app_path())->classes()->implementing(LoggerInterface::class)->bindTo(LoggerService::class)).
    • Facades: Dynamically resolve facades for plugins (e.g., Discover::facades()).
    • Events/Listeners: Auto-register listeners implementing ShouldHandle (e.g., Discover::listenersFor(Event::class)).
  • Non-Laravel PHP:
    • Useful in standalone PHP apps or micro-frameworks needing dynamic class resolution (e.g., CLI tools, libraries).
    • Can integrate with Symfony’s DependencyInjection via custom compilers.

Migration Path

  1. Pilot Phase:
    • Start with non-critical discovery (e.g., logging handlers, test doubles).
    • Example: Replace app()->bind('handler', Handler::class) with:
      Discover::in(app_path('Handlers'))->classes()->implementing(HandlerInterface::class)->bindTo('handler');
      
  2. Incremental Adoption:
    • Phase 1: Replace static bindings in AppServiceProvider.
    • Phase 2: Extend to plugins or modules (e.g., auto-load middleware).
    • Phase 3: Replace custom Reflection-based logic (e.g., in Console commands).
  3. Fallback Mechanism:
    • Maintain hybrid approach: Use Discover for dynamic cases, fall back to manual binding for critical paths.

Compatibility

  • Laravel Versions: Tested on Laravel 9+ (PHP 8.1+). Backporting: For Laravel 8, use spatie/laravel-package-tools to polyfill features (e.g., enums).
  • Package Conflicts: None identified. Lightweight (~1MB) with no global hooks.
  • IDE Support: Works with PHPStorm’s "Go to Implementation" if discovery paths are correctly scoped.

Sequencing

  1. Pre-requisites:
    • Ensure PHP 8.1+ and Laravel 9+ (or polyfills for older versions).
    • Add to composer.json:
      "require": {
          "spatie/laravel-auto-discoverer": "^1.0"
      }
      
  2. Configuration:
    • Publish config (if needed) via php artisan vendor:publish --provider="Spatie\StructureDiscoverer\StructureDiscovererServiceProvider".
    • Configure cache driver (e.g., DISCOVERER_CACHE_DRIVER=file in .env).
  3. Implementation:
    • Replace static bindings with dynamic discovery in AppServiceProvider@boot().
    • Add discovery logic to plugin loaders or module registrars.
  4. Testing:
    • Mock Discover in unit tests or use a test double for deterministic results.
    • Validate cache behavior with Discover::clearCache() tests.
  5. Deployment:
    • Pre-warm cache during deployment (e.g., via post-deploy hook).
    • Monitor cache hit/miss ratios in production.

Operational Impact

Maintenance

  • Pros:
    • Reduced Boilerplate: Eliminates manual bind()/singleton() calls.
    • Centralized Logic: Discovery rules live in one place (e.g., config/discoverer.php).
    • Self-Documenting: Predicates (e.g., implementing(Interface::class)) act as runtime documentation.
  • Cons:
    • Debugging Complexity: Runtime discovery errors (e.g., missing classes) may be harder to trace than static bindings.
    • Cache Management: Requires monitoring cache invalidation (e.g., post-deploy).

Support

  • Proactive Measures:
    • Logging: Log discovery results to storage/logs/discovery.log for auditing.
    • Metrics: Track discovery time via Discover::time() for performance tuning.
  • Common Issues:
    • Class Not Found: Ensure discovery paths include all relevant directories (e.g., app/, modules/*).
    • Cache Staleness: Educate devs to clear cache after adding new classes/interfaces.
  • Documentation:
    • Add a DISCOVERY.md file detailing:
      • Scoped paths (e.g., app/Handlers, plugins/*).
      • Cache strategy (TTL, invalidation).
      • Example predicates for common use cases.

Scaling

  • Performance:
    • Cached Discovery: O(1) lookup after initial O(n) scan. Ideal for large monorepos or plugin systems.
    • Parallel Scanning: For massive codebases, consider parallelizing discovery (e.g., via spatie/async).
  • Resource Usage:
    • Memory: Reflection can be heavy for 10K+ classes. Mitigation: Limit scan scope or use lazy loading.
    • CPU: Initial scan is CPU-intensive. Mitigation: Offload to a queue worker (e.g., Discover::scanInBackground()).
  • Horizontal Scaling:
    • Stateless discovery works in multi-server setups if cache is shared (e.g., Redis).

Failure Modes

Failure Scenario Impact Mitigation
Cache corruption Stale discovery results Use Redis for cache; implement checksum validation.
Missing classes in scan paths Broken bindings/listeners Validate paths in CI; use Discover::paths() to log scanned dirs.
PHP Reflection errors (e.g., missing files)
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.
davejamesmiller/laravel-breadcrumbs
artisanry/parsedown
christhompsontldr/phpsdk
enqueue/dsn
bunny/bunny
enqueue/test
enqueue/null
enqueue/amqp-tools
milesj/emojibase
bower-asset/punycode
bower-asset/inputmask
bower-asset/jquery
bower-asset/yii2-pjax
laravel/nova
spatie/laravel-mailcoach
spatie/laravel-superseeder
laravel/liferaft
nst/json-test-suite
danielmiessler/sec-lists
jackalope/jackalope-transport