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

Proxy Manager Laravel Package

ocramius/proxy-manager

ProxyManager generates and manages PHP proxy classes (virtual proxies, lazy-loading value holders, etc.) to implement the Proxy Pattern. Useful for lazy-loading, interceptors, and advanced DI/ORM scenarios. Install via Composer and use factory helpers to create proxies.

View on GitHub
Deep Wiki
Context7

Getting Started

Install via Composer:

composer require ocramius/proxy-manager

Start with the LazyLoadingValueHolderFactory for lazy-initializing heavy or expensive objects — ideal for service dependencies loaded from containers or databases. The minimal example:

use ProxyManager\Factory\LazyLoadingValueHolderFactory;

$factory = new LazyLoadingValueHolderFactory();

$proxy = $factory->createProxy(
    HeavyService::class,
    static function (&$wrappedObject, $proxy, $method, $params, &$initializer) {
        $wrappedObject = new HeavyService(); // your instantiation logic
        $initializer = null; // one-time init
        return true;
    }
);

// First call triggers lazy init; subsequent calls use the real object
$result = $proxy->doWork();

First stop: docs/lazy-loading-value-holder.md for core usage, initializer signatures, and lifecycle behavior.

Implementation Patterns

  • Dependency Injection Containers (e.g., Symfony, Laravel): Use LazyLoadingValueHolder to defer instantiation of large services (e.g., ORM managers, SDK clients, PDF generators) until actually needed — reduces request warm-up time and memory footprint.

  • Repository Layer with DB Connections: Wrap repository dependencies (like Doctrine EntityManager) in lazy proxies to avoid connecting until query execution. Example for Laravel:

    $factory = new LazyLoadingValueHolderFactory();
    $proxy = $factory->createProxy(
        UserRepository::class,
        static function (&$wrapped) {
            $wrapped = new UserRepository(app('db'));
            $initializer = null;
            return true;
        }
    );
    
  • Access Interceptor Proxies for Cross-Cutting Concerns: Use AccessInterceptorValueHolderFactory for AOP-style logic: logging, rate limiting, caching, and observability hooks without modifying business logic.

    $factory = new AccessInterceptorValueHolderFactory();
    $proxy = $factory->createProxy(
        new ApiClient(),
        // prefix (pre-method)
        ['fetchData' => fn() => logger()->info('API call starting')],
        // suffix (post-method)
        ['fetchData' => fn() => logger()->info('API call finished')]
    );
    
  • Testing & Stubbing: Generate mocks lazily or with intercepted behavior to avoid initializing complex dependencies during unit tests. LazyLoadingValueHolder proxies behave identically to the wrapped object — ideal for test doubles with deterministic setup.

  • Caching Layer Integration: Combine with PSR-6/16 caches: delay expensive object hydration until first method access, then cache the hydrated instance via the initializer.

Gotchas and Tips

  • Initializers Must Be Disabled After Use: Always set $initializer = null (by reference) after first setup — otherwise, the initializer will re-run on every property/method access. Silent performance regressions are common if omitted.

  • Interface Proxies Are Shallow: Proxying an interface (SomeInterface::class) restricts access only to interface methods, even if the wrapped class has more. Use this to reduce proxy size and prevent accidental coupling to implementation details.

  • Avoid func_get_args(): Methods relying on func_get_args(), func_get_arg(), or func_num_args() won’t receive parameters beyond the declared signature — migrate to variadic ...$args instead.

  • No Deep Property Copying: The proxy wraps the object — modifying public properties on the proxy does affect the wrapped object. Not suitable for immutability enforcement.

  • Production Optimization: Use the Config::setGhostObjectLoader() and setProxiesManager() APIs for autoloading generated proxies (avoid runtime reflection overhead). In Laravel, consider caching proxy classes via a custom ServiceProvider or build step.

  • Debugging: Inspect proxies via instanceof LazyLoadingInterface or method_exists($proxy, 'setProxyInitializer') to conditionally log or skip proxy logic in development.

  • Deprecation Warning: The package is unmaintained (last release 2022-03-05). For new projects, consider ocramius/package-versions successor efforts or modern alternatives like Symfony’s ProxyManagerBridge, Doctrine’s Common proxies (which use this package internally), or PHP 8.1+ __callStatic-based lazy patterns. Still safe for existing codebases.

  • Memory Stability: Lazy proxies do not reduce memory until initialized — if the initializer captures large closures or resources, memory may spike at first use. Profile with memory_get_usage() to validate gains.

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
christhompsontldr/phpsdk
enqueue/dsn
bunny/bunny
enqueue/test
enqueue/null
enqueue/amqp-tools
milesj/emojibase
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