Installation Add the package via Composer:
composer require dealroadshow/proximity
No additional configuration is required for basic usage.
First Use Case: Proxying a Class
Create a proxy for an existing class (e.g., UserRepository):
use DealRoadshow\Proximity\Proxy;
$userRepository = new UserRepository();
$proxy = Proxy::create($userRepository);
The proxy will now intercept method calls to the original object.
Where to Look First
src/ directory for core logic).tests/ folder for usage examples and edge cases.Proxy class methods (create(), intercept(), etc.) for core functionality.Transparent Proxying Use proxies to log, validate, or modify method calls without altering the original class:
$proxy = Proxy::create($service)
->intercept('save', function ($args) {
Log::info('Saving entity', $args);
return $service->save(...$args);
});
Dynamic Method Interception Intercept methods dynamically (e.g., for AOP-like behavior):
$proxy = Proxy::create($repository)
->intercept('*', function ($method, $args) {
// Cross-cutting logic (e.g., caching, auth checks)
return $repository->$method(...$args);
});
Integration with Laravel Services
$this->app->bind(UserRepository::class, function ($app) {
return Proxy::create(new EloquentUserRepository())
->intercept('find', fn($args) => $this->logAccess(...$args));
});
$requestProxy = Proxy::create($request)
->intercept('get', fn($key) => $this->sanitizeInput($key));
Testing Mock dependencies with proxies to stub methods:
$mock = Proxy::create(new class { public function riskyOperation() {} })
->intercept('riskyOperation', fn() => 'safe_value');
$this->app->when(UserRepository::class)
->needs('$repository')
->give(fn() => Proxy::create(new EloquentUserRepository()));
$proxy = Proxy::create($model)
->intercept('save', fn($args) => event(new ModelSaved($model)));
Performance Overhead
Static Method Limitations
__callStatic().Closure Scope Issues
$this refers to the proxy, not the original object).bindTo or arrow functions:
->intercept('method', fn($args) => $original->method(...$args))
Magic Methods (__get, __set)
Thread Safety
Proxy::debug(true); // Logs all intercepted calls to storage/logs/proximity.log
$proxy->intercept('method', $firstClosure)->intercept('method', $secondClosure);
Custom Interceptors
Extend the DealRoadshow\Proximity\Interceptor class to add domain-specific logic:
class CacheInterceptor implements Interceptor {
public function __invoke($method, $args) {
// Custom caching logic
}
}
Register via:
$proxy->intercept('*', new CacheInterceptor());
Proxy Factories Create reusable proxy configurations:
class LoggingProxyFactory {
public static function create($object) {
return Proxy::create($object)
->intercept('*', fn($method, $args) => Log::debug("Called {$method}"));
}
}
Integration with Laravel Packages
$jobProxy = Proxy::create($job)
->intercept('handle', fn() => $this->validatePayload());
How can I help you explore Laravel packages today?