infection/include-interceptor
PHP stream wrapper that intercepts the file:// protocol to override the content of any included or autoloaded file at runtime. Register a mapping from original file to replacement, enable the interceptor, and includes/file_get_contents load the replacement instead.
Start by installing the package via Composer: composer require --dev infection/include-interceptor. The package is tiny (a handful of classes) and is meant to be bootstrapped early in your test or instrumentation lifecycle — typically in your test runner’s bootstrap file or before infection runs. Its primary use case is enabling mutation testing tools (like Infection) to track which files are loaded via include/require to ensure mutations in those files are actually executed. To begin, register the interceptor:
use Infection\IncludeInterceptor\Interceptor;
require_once __DIR__ . '/vendor/autoload.php';
$interceptor = new Interceptor();
$interceptor->enable();
Once enabled, every include/require call will be intercepted — you can later retrieve captured events via $interceptor->getInterceptions().
Mutation Testing Integration: Use as a backend for tools like Infection. Wrap test execution with the interceptor to record which files were included during tests — this tells the mutation engine whether a mutation survived because it wasn’t exercised (false positive) or genuinely resilient (true positive).
Test Coverage Expansion: Augment PHPUnit or Pest by registering the interceptor in phpunit.xml’s bootstrap.php. After test runs, analyze included files to detect missing tests that would load additional code paths.
Dynamic Path Rewriting: Implement a custom handler to resolve relative includes to absolute paths or map legacy include patterns (e.g., include 'config.php') to a modern autoloader-based structure during migration.
Conditional Loading Control: Write a handler that blocks inclusion of certain files (e.g., environment-specific configs in tests) to enforce test isolation.
Example workflow in a CLI script:
$interceptor->enable();
// Run your tests or analysis
$exitCode = include 'run-tests.php';
$interceptions = $interceptor->getInterceptions();
foreach ($interceptions as $file => $count) {
echo "$file was included $count time(s)\n";
}
Autoloader Conflicts: Since it operates via stream wrappers, avoid enabling the interceptor after spl_autoload_register() has been used heavily; some autoloaders may bypass the intercepted includes entirely if they resolve paths manually.
Once vs. Twice: include_once/require_once behavior is preserved — the interceptor respects PHP’s internal “already included” cache, so duplicate includes won’t be re-logged. Don’t expect multiple events for the same file unless you manually reset PHP’s internal state (not recommended).
Handler Ordering: If multiple packages install stream wrappers (e.g., Xdebug, other interceptors), order matters. Call enable() early, and prefer using stream_wrapper_unregister() + re-registration only if you need to chain handlers — the package does not support chaining natively.
Performance Overhead: While lightweight, the overhead is non-zero. Disable it outside of CLI/test contexts (e.g., wrap in if (PHP_SAPI === 'cli')).
PHP Version Constraints: The package targets PHP 7.4+ (based on release date and usage patterns). Avoid on HHVM or older PHP versions.
No Public API for Modifying Behavior at Runtime: Handlers are set once on enable(). If you need dynamic behavior (e.g., switch based on test group), build your own wrapper class that implements stream_wrapper_register() logic around the interceptor’s internal logic — but consult its source first (simple ~300-line repo).
How can I help you explore Laravel packages today?