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

Patchwork Laravel Package

antecedent/patchwork

Patchwork is a PHP library for monkey patching: redefine functions, methods, and classes at runtime to ease testing and legacy refactors. Works with Composer and popular test tools, enabling stubs/mocks without changing existing code.

Deep Wiki
Context7

Technical Evaluation

Architecture Fit

  • Monkey patching aligns with Laravel’s dynamic runtime needs (e.g., testing legacy services, third-party SDKs, or core framework internals without modifying source).
  • Runtime interception complements Laravel’s event system and service container but operates at a lower level (bytecode manipulation vs. DI container overrides).
  • Legacy testing is a critical use case for Laravel monoliths or inherited codebases where refactoring is constrained by business risk or technical debt.
  • Potential conflicts: Patchwork’s runtime rewrites may interfere with Laravel’s autoloader (Composer), OPcache, or framework-level optimizations (e.g., Bootstrap/HandleExceptions). Overrides to core PHP functions (e.g., array_map, json_encode) could destabilize Laravel’s assumptions.

Integration Feasibility

  • PHP 8.1+ compatibility: Patchwork’s last release (2025) suggests modern PHP support, but Laravel’s long-term support (LTS) cycles (e.g., Laravel 10+ on PHP 8.2+) must be validated.
  • Laravel-specific hooks: Integration via registerShutdownFunction or spl_autoload_register could conflict with Laravel’s bootstrap/app.php or composer.json autoloading. A dedicated PatchworkServiceProvider would mitigate this.
  • Testing frameworks: Native support for PHPUnit/Pest stubs/spies reduces need for Patchwork, but its global function patching (e.g., DB::connection()) fills gaps in Laravel’s mocking tools.

Technical Risk

  • OPcache incompatibility: Runtime rewrites may bypass OPcache optimizations, degrading performance in production. Requires explicit opcache.reset() or disabling OPcache in test environments.
  • Static analysis tools: Tools like Psalm or PHPStan may flag patched methods as "undefined" or "unused," requiring custom rules.
  • Thread safety: Patchwork’s runtime modifications are not thread-safe; Laravel’s queue workers or Horizon could exhibit race conditions if patches are applied dynamically.
  • Debugging complexity: Stack traces for patched code may obscure original call sites, complicating error resolution.

Key Questions

  1. Scope of patching:
    • Will patches target userland code only (e.g., legacy services) or core PHP/Laravel functions (e.g., Str::of(), Cache::remember)?
    • Are there whitelisted/blacklisted functions to avoid unintended side effects?
  2. Environment isolation:
    • How will patches be scoped to test environments only (e.g., via .env flags or CI checks)?
    • Can Patchwork coexist with Laravel’s container binding overrides or facade mocking?
  3. Performance impact:
    • What’s the baseline overhead of runtime rewrites in production-like loads?
    • Are there OPcache or JIT compiler workarounds to mitigate slowdowns?
  4. Maintenance:
    • How will patched code be documented (e.g., PHPDoc annotations, README warnings)?
    • What’s the deprecation path for patches that become permanent features?
  5. Alternatives:
    • Could Laravel’s built-in testing tools (e.g., Mockery, partial mocks) or dependency injection suffice for 80% of use cases?
    • Are there composer packages (e.g., brick/math, mockery) that offer safer alternatives?

Integration Approach

Stack Fit

  • Primary use case: Legacy code testing in Laravel monoliths where DI is impractical (e.g., static classes, global helpers, or third-party SDKs).
  • Secondary use cases:
    • Debugging: Temporarily modifying behavior in production (e.g., rate-limiting a legacy API call).
    • Prototyping: Quickly testing hypotheses without committing to refactors.
    • A/B testing: Runtime feature flags for experimental logic.
  • Compatibility:
    • Laravel 10+: Tested with PHP 8.2+; validate against Laravel’s bootstrap/app.php autoloader.
    • Composer: Install as a dev dependency to avoid production bloat.
    • Testing frameworks: Integrate with PHPUnit/Pest via setUp() or beforeEach() to apply patches per test.

Migration Path

  1. Pilot phase:
    • Start with non-critical legacy modules (e.g., a deprecated payment gateway).
    • Use Patchwork to stub external APIs or mock static methods (e.g., LegacyAuth::check()).
  2. Tooling integration:
    • Create a custom PHPUnit extension to auto-apply patches for specific test classes.
    • Example:
      // tests/TestCase.php
      use antecedent\Patchwork\Patchwork;
      
      protected function setUp(): void {
          parent::setUp();
          Patchwork::when('LegacyService::process')
              ->thenReturn(fn($input) => 'mocked_' . $input);
      }
      
  3. Gradual adoption:
    • Replace direct function calls in tests with patched versions.
    • Document patched functions in a PATCHES.md file with:
      • Original function signature.
      • Patch purpose (e.g., "Mocks DB::raw() for legacy queries").
      • Test coverage scope.

Compatibility

  • Laravel-specific considerations:
    • Service Container: Patchwork can override container bindings, but prefer Laravel’s bind() or extend() for consistency.
    • Facades: Use Patchwork to intercept static facade calls (e.g., Cache::get()) but avoid patching Laravel’s internal facade handlers.
    • Events: Patchwork can’t replace Laravel’s event system but can intercept event listeners (e.g., Event::listen()).
  • Conflict resolution:
    • Order of operations: Apply patches after Laravel’s bootstrap but before test execution.
    • Patch precedence: Use Patchwork::priority() to ensure critical patches (e.g., security overrides) take effect first.

Sequencing

  1. Development:
    • Apply patches in tests/CreatesApplication or a dedicated PatchworkServiceProvider.
    • Example provider:
      // app/Providers/PatchworkServiceProvider.php
      public function boot() {
          if (app()->environment('testing')) {
              Patchwork::when('App\Legacy\Helper::deprecatedMethod')
                  ->then(fn(...$args) => throw new \RuntimeException('Deprecated!'));
          }
      }
      
  2. CI/CD:
    • Enable patches only in test pipelines (e.g., via PHPUNIT_PATCHWORK_ENABLED=true).
    • Add a pre-test hook to validate no patches remain in production builds.
  3. Production:
    • Avoid runtime patches unless absolutely necessary (e.g., emergency fixes).
    • Use feature flags or config-based toggles instead of monkey patching.

Operational Impact

Maintenance

  • Patch documentation:
    • Require Jira/GitHub issue links for each patch explaining its purpose and expiration date.
    • Example template:
      // PATCH: LegacyAuth::validate() -> throws AuthException for testing
      // Issue: LARAVEL-1234 | Expires: 2025-12-31
      // Reason: Bypass legacy auth for migration tests.
      
  • Deprecation process:
    • Schedule quarterly reviews to remove unused patches.
    • Replace patches with proper DI solutions or framework features (e.g., Laravel 11’s improved testing tools).
  • Tooling:
    • Integrate with PHPStan to suppress false positives for patched methods:
      // phpstan.neon
      arguments:
          level: 5
          checkMissingIterableValueType: false
          checkPropertyAssignmentInConstructor: false
      

Support

  • Debugging challenges:
    • Stack traces: Patched code may hide original callers. Use Patchwork::dump() to inspect active patches.
    • Environment drift: Patches applied in staging may not replicate in production due to PHP version differences.
  • Support workflow:
    • Patchwork-specific logs: Add middleware to log patch activations in production:
      // app/Http/Middleware/LogPatches.php
      public function handle($request, Closure $next) {
          if (Patchwork::hasActivePatches()) {
              \Log::warning('Active patches detected', ['patches' => Patchwork::listPatches()]);
          }
          return $next($request);
      }
      
    • Incident response: Treat unexpected patches in production as P0 incidents (e.g., a patched Auth::check() breaking login flows).

Scaling

  • Performance:
    • Benchmark patches: Use laravel-debugbar to measure runtime overhead.
    • OPcache workarounds: Disable OPcache in test environments or use Patchwork::clear() between tests.
  • Concurrency:
    • **Queue
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
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
twbs/bootstrap4
php-http/client-implementation
phpcr/phpcr-implementation
cucumber/gherkin-monorepo
haydenpierce/class-finder
psr/simple-cache-implementation
uri-template/tests