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 structures in your codebase. Find classes, interfaces, traits, and enums by conditions like “implements interface” or “uses trait,” and get rich metadata. Ideal for automation, registration, and scanning in production.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation:

    composer require spatie/php-structure-discoverer
    

    For Laravel, publish the config:

    php artisan vendor:publish --tag="structure-discoverer-config"
    
  2. First Use Case: Discover all classes implementing Arrayable in app/:

    use Spatie\StructureDiscoverer\Discover;
    
    $arrayableClasses = Discover::in(app_path())->classes()->implementing(\Illuminate\Contracts\Support\Arrayable::class)->get();
    

Key Starting Points

  • Basic Discovery: Use Discover::in(__DIR__)->get() to retrieve all structures (classes, interfaces, enums, traits).
  • Laravel Integration: Configure cache drivers in config/structure-discoverer.php (default: LaravelDiscoverCacheDriver).
  • Documentation: Focus on the Usage section for fluent API methods.

Implementation Patterns

Core Workflows

1. Discovering Structures by Type

  • Classes: Discover::in(__DIR__)->classes()->get()
  • Interfaces: Discover::in(__DIR__)->interfaces()->get()
  • Enums: Discover::in(__DIR__)->enums()->get()
  • Traits: Discover::in(__DIR__)->traits()->get()

2. Filtering with Conditions

  • Extending/Implementing:
    Discover::in(__DIR__)->extending(\Illuminate\Database\Eloquent\Model::class)->get();
    Discover::in(__DIR__)->implementing(\JsonSerializable::class)->get();
    
  • Attributes:
    Discover::in(__DIR__)->withAttribute(\Spatie\LaravelActivitylog\Traits\LogsActivity::class)->get();
    
  • Custom Logic:
    Discover::in(__DIR__)->custom(fn($structure) => str_contains($structure->namespace, 'App\\Policies'))->get();
    

3. Combining Conditions

  • AND Logic (Default):
    Discover::in(__DIR__)->classes()->implementing(\Arrayable::class)->get();
    
  • OR Logic:
    use Spatie\StructureDiscoverer\ConditionBuilder;
    Discover::in(__DIR__)
        ->any(
            ConditionBuilder::create()->classes(),
            ConditionBuilder::create()->enums()
        )
        ->get();
    

4. Caching with Structure Scouts

  • Define a Scout:
    class PolicyScout extends \Spatie\StructureDiscoverer\StructureScout
    {
        protected function definition(): \Spatie\StructureDiscoverer\Discover
        {
            return Discover::in(app_path('Policies'))->classes();
        }
    }
    
  • Use in Code:
    $policies = PolicyScout::create()->get(); // Cached after first run
    
  • Warm Cache (Laravel):
    php artisan structure-scouts:cache
    

5. Parallel Scanning (Large Codebases)

Discover::in(base_path())->parallel(100)->get(); // Scan 100 files per process

Integration Tips

  • Laravel Service Providers: Register scouts in boot():
    public function boot()
    {
        \Spatie\StructureDiscoverer\StructureScoutManager::add(\App\Scouts\PolicyScout::class);
    }
    
  • Dynamic Directories: Pass directories dynamically:
    $directories = [app_path('Models'), app_path('Policies')];
    Discover::in(...$directories)->get();
    
  • Testing: Use NullDiscoverCacheDriver to bypass caching:
    Discover::in(__DIR__)->withCache('test', new \Spatie\StructureDiscoverer\Cache\NullDiscoverCacheDriver())->get();
    

Gotchas and Tips

Pitfalls

  1. Performance in Development:

    • Disable caching in development to avoid stale data:
      Discover::in(__DIR__)->withCache('dev', new \Spatie\StructureDiscoverer\Cache\NullDiscoverCacheDriver())->get();
      
    • Fix: Use NullDiscoverCacheDriver or clear cache frequently:
      php artisan structure-scouts:clear
      
  2. Chains Overhead:

    • Resolving inheritance chains (extendsChain, implementsChain) is resource-intensive.
    • Fix: Disable chains when not needed:
      Discover::in(__DIR__)->withoutChains()->extending(\Model::class)->get();
      
  3. Case Sensitivity:

    • File system sorting (e.g., Sort::Name) may behave unexpectedly across OSes.
    • Fix: Use Sort::CaseInsensitiveName for consistent results.
  4. Ignored Files:

    • Default ignored files (e.g., vendor/, node_modules/) are not configurable via the package.
    • Fix: Filter results post-discovery or use a custom DiscoverCondition.
  5. Parallel Scanning Limitations:

    • Requires amphp/parallel and may not work in all environments (e.g., shared hosting).
    • Fix: Fall back to non-parallel mode:
      Discover::in(__DIR__)->get(); // No ->parallel()
      

Debugging Tips

  • Inspect Raw Data: Use full() to debug DiscoveredStructure objects:
    $structures = Discover::in(__DIR__)->full()->get();
    dd($structures[0]->extendsChain); // Example: Inspect inheritance chain
    
  • Cache Debugging: Check cache keys manually:
    $cacheDriver = app(\Spatie\StructureDiscoverer\Cache\LaravelDiscoverCacheDriver::class);
    $cacheDriver->has('your_scout_id'); // Verify cache existence
    
  • Slow Queries: Profile with Xdebug or Laravel Debugbar to identify bottlenecks in large codebases.

Extension Points

  1. Custom Cache Drivers: Implement DiscoverCacheDriver for specialized storage (e.g., Redis):

    class RedisDiscoverCacheDriver implements \Spatie\StructureDiscoverer\Cache\DiscoverCacheDriver
    {
        public function has(string $id): bool { /* ... */ }
        // Implement other methods...
    }
    
  2. Custom Conditions: Extend DiscoverCondition for reusable logic:

    class HasAttributeCondition extends \Spatie\StructureDiscoverer\DiscoverCondition
    {
        public function __construct(private string $attributeFqcn) {}
        public function satisfies(DiscoveredStructure $structure): bool {
            return in_array($this->attributeFqcn, $structure->attributes, true);
        }
    }
    
  3. Laravel Service Provider Hooks: Override scout directories in register():

    $this->app->singleton('structure-discoverer.directories', fn() => [
        app_path(),
        database_path('Scouts'),
    ]);
    
  4. Artisan Commands: Extend StructureScoutsCommand to add custom cache warming logic:

    class CustomScoutsCommand extends \Spatie\StructureDiscoverer\Console\StructureScoutsCommand
    {
        protected function getScoutClasses(): array {
            return [\App\Scouts\CustomScout::class];
        }
    }
    

Configuration Quirks

  • Cache Store: The store key in config/structure-discoverer.php must match a Laravel cache driver (e.g., redis, database). Fix: Set to null to use the default store:

    'cache' => [
        'driver' => \Spatie\StructureDiscoverer\Cache\LaravelDiscoverCacheDriver::class,
        'store' => null, // Uses default Laravel cache
    ]
    
  • Directory Traversal: Avoid traversing into vendor/ or node_modules/ to prevent performance issues. Fix: Exclude directories in custom conditions:

    Discover::in(__DIR__)->custom(fn($structure) => !str_contains($structure->file, 'vendor'))->get();
    
  • Namespace Conflicts: Ensure scout classes are in a unique namespace to avoid collisions. Fix: Use a dedicated namespace (e.g., App\Scouts).

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.
hexters/coinpayment
rjcodes/rjcms
act-training/laravel-permissions-manager
alimarchal/laravel-chart-of-accounts
babenkoivan/elastic-scout-driver
mkwebdesign/filament-watchdog-v5
renatomarinho/laravel-page-speed
zedmagdy/filament-business-hours
renatovdemoura/blade-elements-ui
devgeek/beacon-admin
benjamin-rqt/data-watcher-bundle
atriumphp/atrium
sandermuller/package-boost-laravel
sandermuller/boost-skills
redaxo/core
yusufgenc/filament-api-forge
l3aro/rating-star-for-filament
leek/filament-subtenant-scope
anil/file-picker
broqit/fields-ai