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

Change Detector Laravel Package

typhoon/change-detector

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation:

    composer require typhoon/change-detector
    
  2. Basic Usage:

    use Typhoon\ChangeDetector\ChangeDetectors;
    use Typhoon\ChangeDetector\FileChangeDetector;
    
    // Detect file changes (e.g., config file)
    $detector = FileChangeDetector::fromFile('/path/to/config/app.php');
    if ($detector->changed()) {
        // Trigger cache rebuild or other actions
        Artisan::call('config:clear');
    }
    
    // Detect PHP version changes
    $phpDetector = ChangeDetectors::phpVersion('8.1.0');
    if ($phpDetector->changed()) {
        Log::warning('PHP version changed; validate compatibility.');
    }
    
  3. First Use Case:

    • Cache Invalidation: Check bootstrap/cache/config.php before serving cached responses:
      $cacheDetector = FileChangeDetector::fromFile(base_path('bootstrap/cache/config.php'));
      if ($cacheDetector->changed()) {
          Cache::forget('config');
      }
      

Where to Look First

  • Detectors: Explore src/ChangeDetector/ for available detectors:
    • FileChangeDetector (filesystem changes)
    • PhpVersionChangeDetector (PHP version shifts)
    • ComposerPackageChangeDetector (Composer dependency updates)
    • ConstantChangeDetector (runtime constant values)
  • Factory: ChangeDetectors::from() for combining detectors with a default fallback.
  • Changelog: Review 0.4.4 for critical fixes (e.g., inverted logic in version detectors).

Implementation Patterns

Core Workflows

1. File Change Detection

// Single file
$detector = FileChangeDetector::fromFile('/path/to/file.php');
if ($detector->changed()) {
    // Handle change
}

// Multiple files with ignore patterns
$detector = FileChangeDetector::fromFiles([
    'config/app.php',
    'routes/web.php',
])->ignore('vendor/**', 'node_modules/**');

2. Composer Dependency Tracking

// Track a specific package version
$detector = ChangeDetectors::composerPackage('laravel/framework', '^10.0');
if ($detector->changed()) {
    Log::alert('Laravel framework version changed!');
}

// Track all dev dependencies
$detector = ChangeDetectors::composerPackage('*', '*', true); // dev-only

3. PHP Environment Validation

// Detect PHP version changes
$detector = ChangeDetectors::phpVersion('8.1.0');
if ($detector->changed()) {
    throw new RuntimeException('PHP version mismatch detected.');
}

// Detect extension presence
$detector = ChangeDetectors::phpExtension('redis');
if (!$detector->exists()) {
    throw new RuntimeException('Redis extension required.');
}

4. Combined Detectors with Fallback

// Check config file OR PHP version
$detector = ChangeDetectors::from([
    FileChangeDetector::fromFile('config/app.php'),
    ChangeDetectors::phpVersion('8.1.0'),
], false); // Return true if ANY detector changes

if ($detector->changed()) {
    Artisan::call('optimize:clear');
}

Laravel-Specific Patterns

Event-Driven Cache Invalidation

// app/Providers/ChangeDetectorServiceProvider.php
use Illuminate\Support\Facades\Event;
use Typhoon\ChangeDetector\FileChangeDetector;

public function boot(): void
{
    Event::listen('filesystem.updated', function ($event) {
        $detector = FileChangeDetector::fromFile($event->path);
        if ($detector->changed()) {
            Cache::forget('config');
        }
    });
}

Artisan Commands for Manual Checks

// app/Console/Commands/CheckChanges.php
use Typhoon\ChangeDetector\ChangeDetectors;

protected $signature = 'change:detect {--check= : Comma-separated checks (file,php,composer)}';
public function handle()
{
    $checks = explode(',', $this->option('check'));

    if (in_array('file', $checks)) {
        $this->checkFiles();
    }

    if (in_array('php', $checks)) {
        $this->checkPhpVersion();
    }
}

private function checkFiles(): void
{
    $detector = FileChangeDetector::fromFiles([
        'config/app.php',
        'routes/web.php',
    ]);
    if ($detector->changed()) {
        $this->info('Files changed. Clearing cache...');
        Artisan::call('config:clear');
    }
}

Service Container Integration

// config/app.php
'providers' => [
    // ...
    Typhoon\ChangeDetector\ChangeDetectorServiceProvider::class,
],

// Register detectors as singletons
'change_detectors' => [
    'config' => \Typhoon\ChangeDetector\FileChangeDetector::fromFile(config_path('app.php')),
    'routes' => \Typhoon\ChangeDetector\FileChangeDetector::fromFile(base_path('routes/web.php')),
],

CI/CD Pipeline Integration

# .github/workflows/change-detection.yml
jobs:
  detect-changes:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-php@v3
        with:
          php-version: '8.1'
      - run: composer install
      - run: |
          php artisan change:detect --check=file,composer
          if [ $? -eq 1 ]; then
            echo "Changes detected! Triggering rebuild..."
            # Add your rebuild logic here
          fi

Extending the Package

Custom Detectors

use Typhoon\ChangeDetector\ChangeDetector;

class DatabaseSchemaDetector implements ChangeDetector
{
    public function changed(): bool
    {
        $currentSchema = $this->getCurrentSchemaHash();
        return $currentSchema !== cache('schema_hash');
    }

    private function getCurrentSchemaHash(): string
    {
        // Implement logic to generate a hash of your schema
        return hash('sha256', Schema::getRawSchema());
    }
}

// Register in ChangeDetectors::from()
$detector = ChangeDetectors::from([
    new DatabaseSchemaDetector(),
], false);

Composite Detectors

use Typhoon\ChangeDetector\CompositeChangeDetector;

$composite = new CompositeChangeDetector([
    FileChangeDetector::fromFile('config/app.php'),
    ChangeDetectors::phpVersion('8.1.0'),
    ChangeDetectors::composerPackage('laravel/framework', '^10.0'),
]);

if ($composite->changed()) {
    // Handle any change
}

Gotchas and Tips

Pitfalls

  1. Inverted Logic in Version Detectors

    • Issue: Versions 0.4.3 and 0.4.4 fixed inverted logic in PhpVersionChangeDetector and PhpExtensionVersionChangeDetector. Always verify changed() returns true when expected.
    • Fix: Test with known version changes:
      $detector = ChangeDetectors::phpVersion('8.0.0');
      $detector->changed(); // Should return true if PHP >= 8.1.0
      
  2. Filesystem Permissions

    • Issue: FileChangeDetector may fail silently if it lacks read permissions for a file.
    • Fix: Wrap in a try-catch or use File::exists() first:
      if (!File::exists($path)) {
          throw new RuntimeException("File not found: {$path}");
      }
      
  3. Composer Lock File Changes

    • Issue: ComposerPackageChangeDetector may trigger false positives during composer install if composer.lock is updated but dependencies haven’t changed.
    • Fix: Compare composer.json + composer.lock hashes:
      $jsonHash = hash_file('sha256', 'composer.json');
      $lockHash = hash_file('sha256', 'composer.lock');
      if ($jsonHash !== cache('composer_json_hash') || $lockHash !== cache('composer_lock_hash')) {
          // Changes detected
      }
      
  4. Time-Based Optimizations

    • Issue: Disabling mtime checks in FileChangeDetector (via withoutMtime()) may lead to missed changes if files are modified but mtime isn’t updated (e.g., symlinks).
    • Fix: Use content hashing as a fallback:
      $detector = FileChangeDetector::fromFile($path)
          ->withoutMtime()
          ->withContentHash();
      
  5. PHP Constants Caching

    • Issue: ConstantChangeDetector may return stale results if constants are defined in included files that aren’t re-evaluated.
    • Fix: Clear OPcache or
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.
jayeshmepani/jpl-moshier-ephemeris-php
elnasnato/laraliveui
labrodev/rest-sdk
sampaui/sampaui
babelqueue/php-sdk
facebook/capi-param-builder-php
babelqueue/symfony
hamzi/corewatch
minionfactory/raw-hydrator
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