PHP Structure Discoverer

repository·main·Indexed 41 days ago

https://github.com/spatie/php-structure-discoverer

A tool for automatically discovering PHP classes, interfaces, enums, and traits based on specific conditions. It features built-in caching via StructureScouts, parallel scanning support using amphp/parallel, and deep integration for Laravel applications including dedicated CLI commands for cache management.

Tokens
4.7K
Snippets
21
Records
24
Agent score
52%

What's inside PHP Structure Discoverer

  1. Combine conditions using AND and OR logic

    main

    By default, chaining methods performs an AND operation. To perform OR operations or complex nested logic, use ConditionBuilder with the any() method.

    // AND: Classes that implement Arrayable
    Discover::in(__DIR__)->classes()->implementing(Arrayable::class)->get();
    
    // OR: Classes OR Enums
    Discover::in(__DIR__)
        ->any(
            ConditionBuilder::create()->classes(),
            ConditionBuilder::create()->enums()
        )
        ->get();
    
    // Complex: (Classes AND implementing Arrayable) OR (Enums AND implementing Stringable)
    Discover::in(__DIR__)
        ->any(
            ConditionBuilder::create()->exact(
                ConditionBuilder::create()->classes()->implementing(Arrayable::class),
            ),
            ConditionBuilder::create()->exact(
                ConditionBuilder::create()->enums()->implementing(Stringable::class),
            )
        )
        ->get();
  2. How inheritance chains work

    main

    By default, the package resolves inheritance chains. If you discover a class extending Request, it will also find FormRequest and UserFormRequest if they exist in the scanned directories.

    To disable this behavior, use:

    • extendingWithoutChain(string $class)
    • implementingWithoutChain(string $interface)
    • withoutChains() (disables for all discovery operations)

    Note: Resolving chains is resource-heavy; disabling them can improve performance.

    // Disable chain resolution entirely
    Discover::in(__DIR__)->withoutChains()->extending(Request::class)->get();
  3. Basic usage of the Discover class

    main

    To start discovering structures, use Discover::in() to specify the directories to scan. By default, get() returns an array of Fully Qualified Class Names (FCQN) for all classes, enums, interfaces, and traits found.

    // Scan a single directory
    Discover::in(__DIR__)->get();
    
    // Scan multiple directories
    Discover::in(app_path('models'), app_path('enums'))->get();
  4. Enable parallel scanning

    main

    For large applications, you can speed up discovery by using parallel processing. This requires the amphp/parallel package.

    Install the dependency:

    composer require amphp/parallel

    Enable it in your discovery chain:

    • parallel(): Enables parallel scanning.
    • parallel(int $files): Sets the number of files each process scans (default is 50).
    // Default (50 files per process)
    Discover::in(__DIR__)->parallel()->get();
    
    // Custom file count per process
    Discover::in(__DIR__)->parallel(100)->get();
  5. Cache discovered structures using StructureScouts

    main

    To avoid expensive scanning in production, use StructureScout classes. A scout defines what to discover and how to cache it.

    Implementing a Scout

    Extend StructureScout and implement definition() and cacheDriver().

    Using a Scout

    Call create()->get() on your scout class.

    Production Management

    • Warm Cache: Use StructureScoutManager::cache([directory]) or php artisan structure-scouts:cache (Laravel).
    • Clear Cache: Use StructureScoutManager::clear([directory]) or php artisan structure-scouts:clear (Laravel).
    • Manual Addition: For packages, use StructureScoutManager::add(YourScout::class) in a ServiceProvider.
    class EnumsStructureScout extends StructureScout
    {
        protected function definition(): Discover|DiscoverConditionFactory
        {
            return Discover::in(__DIR__)->enums();
        }
    
        public function cacheDriver(): DiscoverCacheDriver
        {
            return new FileDiscoverCacheDriver('/path/to/temp/directory');
        }
    }
    
    // Usage
    EnumsStructureScout::create()->get();
  6. Configure the structure discoverer in Laravel

    main

    After publishing the config, you can manage the following keys in your configuration file:

    • ignored_files: An array of files to skip during discovery.
    • structure_scout_directories: An array of directories where the package will search for structures.
    • cache: Configuration for the cache driver. By default, it uses \Spatie\StructureDiscoverer\Cache\LaravelDiscoverCacheDriver::class.
    return [
        /*
         *  A list of files that should be ignored during the discovering process.
         */
        'ignored_files' => [
    
        ],
    
        /**
         * The directories where the package should search for structure scouts
         */
        'structure_scout_directories' => [
            app_path(),
        ],
    
        /*
         *  Configure the cache driver for discoverers
         */
        'cache' => [
            'driver' => \Spatie\StructureDiscoverer\Cache\LaravelDiscoverCacheDriver::class,
            'store' => null,
        ]
    ];
  7. Discover classes implementing an interface

    main

    Use the Discover class to find structures within a specific directory that meet certain criteria. You can chain methods like classes(), interfaces(), enums(), or traits() with conditions like implementing() to filter results.

    use Spatie\StructureDiscoverer\Discover;
    
    // Returns an array of classes implementing Arrayable::class
    Discover::in(__DIR__)->classes()->implementing(Arrayable::class)->get(); 
  8. Sort discovered structures

    main

    Use sortBy() to change the order of the returned array. Available options from the Spatie\StructureDiscoverer\Enums\Sort enum include:

    • Sort::Name / Sort::CaseInsensitiveName
    • Sort::Size
    • Sort::Type
    • Sort::Extension
    • Sort::ChangedTime
    • Sort::ModifiedTime
    • Sort::AccessedTime
    use Spatie\StructureDiscoverer\Enums\Sort;
    
    Discover::in(__DIR__)->sortBy(Sort::Name)->get();