laravel-proxy-manager - Integrate Ocramius/ProxyManager into a Laravel application.

Function

  • Quickly create different types of proxy instances.
  • Quickly bind different types of proxy instances to containers.
  • Rapid scaling for different types of proxy instances to containers.

Install

 $ composer require guanguans/laravel-proxy-manager -vvv
 $ php artisan vendor:publish --provider="Guanguans\\LaravelProxyManager\\ProxyManagerServiceProvider"

use

Get proxy manager instance

 app(\Guanguans\LaravelProxyManager\ProxyManager::class);
resolve(\Guanguans\LaravelProxyManager\ProxyManager::class);

Proxy Manager Facade Methods

 <?php

namespace Guanguans\LaravelProxyManager\Facades;

/**
 * 创建代理
 * @method static \ProxyManager\Proxy\AccessInterceptorInterface            createAccessInterceptorScopeLocalizerProxy(object $instance, array $prefixInterceptors = [], array $suffixInterceptors = [])
 * @method static \ProxyManager\Proxy\AccessInterceptorValueHolderInterface createAccessInterceptorValueHolderProxy(object $instance, array $prefixInterceptors = [], array $suffixInterceptors = [])
 * @method static \ProxyManager\Proxy\GhostObjectInterface                  createLazyLoadingGhostFactoryProxy(string $className, \Closure $initializer, array $proxyOptions = [])
 * @method static \ProxyManager\Proxy\VirtualProxyInterface                 createLazyLoadingValueHolderProxy(string $className, \Closure $initializer, array $proxyOptions = [])
 * @method static \ProxyManager\Proxy\NullObjectInterface                   createNullObjectProxy($instanceOrClassName)
 * @method static \ProxyManager\Proxy\RemoteObjectInterface                 createRemoteObjectProxy($instanceOrClassName, ?\ProxyManager\Factory\RemoteObject\AdapterInterface $adapter = null)
 *
 * 绑定代理
 * @method static void                                                      singletonLazyLoadingValueHolderProxy(string $className, ?\Closure $concrete = null)
 * @method static void                                                      bindLazyLoadingValueHolderProxy(string $className, ?\Closure $concrete = null, bool $shared = false)
 * @method static void                                                      singletonNullObjectProxy(string $className)
 * @method static void                                                      bindNullObjectProxy(string $className, bool $shared = false)
 * @method static void                                                      singletonRemoteObjectProxy(string $className, ?\ProxyManager\Factory\RemoteObject\AdapterInterface $adapter = null)
 * @method static void                                                      bindRemoteObjectProxy(string $className, ?\ProxyManager\Factory\RemoteObject\AdapterInterface $adapter = null, bool $shared = false)
 * 
 * 扩展为代理
 * @method static void                                                      extendToAccessInterceptorScopeLocalizerProxy(string $abstract, array $prefixInterceptors = [], array $suffixInterceptors = [])
 * @method static void                                                      extendToAccessInterceptorValueHolderProxy(string $abstract, array $prefixInterceptors = [], array $suffixInterceptors = [])
 * @method static void                                                      extendToLazyLoadingGhostFactoryProxy(string $abstract, \Closure $initializer, array $proxyOptions = [])
 * @method static void                                                      extendToLazyLoadingValueHolderProxy(string $abstract, \Closure $initializer, array $proxyOptions = [])
 * @method static void                                                      extendToNullObjectProxy(string $abstract)
 * @method static void                                                      extendToRemoteObjectProxy(string $abstract, ?\ProxyManager\Factory\RemoteObject\AdapterInterface $adapter = null)
 *
 * @see \Guanguans\LaravelProxyManager\ProxyManager
 */
class ProxyManager{}

Binding virtual proxy example (lazy initialization)

 <?php

namespace App;

use App\Foo;
use Guanguans\LaravelProxyManager\Facades\ProxyManager;
use SebastianBergmann\Timer\ResourceUsageFormatter;
use SebastianBergmann\Timer\Timer;

class Foo
{
    /** @var string */
    private $bar;

    public function __construct(string $bar = 'bar')
    {
        $this->bar = $bar;
        sleep(3);
    }

    public function getBar(): string
    {
        return $this->bar;
    }
}

// ProxyManager::bindLazyLoadingValueHolderProxy(Foo::class);
ProxyManager::singletonLazyLoadingValueHolderProxy(Foo::class);

$formatter = new ResourceUsageFormatter();
$timer = new Timer();
$timer->start();
$timer->start();

// 初始代理类时不会调用原类的构造函数
dump($foo = app(Foo::class), $formatter->resourceUsage($timer->stop()));
// 当真正调用时才会调用原类的构造函数
dump($foo->getBar(), $formatter->resourceUsage($timer->stop()));
 ProxyManagerGeneratedProxy\__PM__\App\Foo\Generated5320f6306ba550844e07c949e4af382d - App\Foo@proxy {#774
  -valueHolder1cdad: null
  -initializer7920c: Closure(?object &$wrappedObject, ?object $proxy, string $method, array $parameters, ?Closure &$initializer) {#758
    class: "Guanguans\LaravelProxyManager\ProxyManager"
    this: Guanguans\LaravelProxyManager\ProxyManager {#755 …}
    use: {
      $className: "App\Foo"
      $classArgs: []
    }
    file: "/Users/yaozm/Documents/develop/laravel-proxy-manager/src/ProxyManager.php"
    line: "282 to 287"
  }
}
"Time: 00:00.008, Memory: 20.00 MB"
"bar"
"Time: 00:03.025, Memory: 22.00 MB"

Extended to access interceptor proxy example (aspect)

 ProxyManager::extendToAccessInterceptorValueHolderProxy(
    LogManager::class,
    [
        'error' => static function (
            object $proxy,
            LogManager $realInstance,
            string $method,
            array $parameters,
            bool &$returnEarly
        ){
            dump('Before executing the error log method.');
        }
    ],
    [
        'error' => static function (
            object $proxy,
            LogManager $realInstance,
            string $method,
            array $parameters,
            &$returnValue,
            bool &$overrideReturnValue
        ){
            dump('After executing the error log method.');
        }
    ]
);

dump($logger = app(LogManager::class));
$logger->error('What happened?');
 ProxyManagerGeneratedProxy\__PM__\Illuminate\Log\LogManager\Generated9b66c8f3bc457c2c26acc55874d391b3 - Illuminate\Log\LogManager@proxy {#298 ▼
  -valueHolder8f21a: Illuminate\Log\LogManager {#168 ▼
    #app: Illuminate\Foundation\Application {#6 ▶}
    #channels: []
    #customCreators: array:1 [▶]
    #dateFormat: "Y-m-d H:i:s"
    #levels: array:8 [▶]
  }
  -methodPrefixInterceptors8d709: array:1 [▼
    "error" => Closure(object $proxy, LogManager $realInstance, string $method, array $parameters, bool &$returnEarly) {#280 ▶}
  ]
  -methodSuffixInterceptors2a12b: array:1 [▼
    "error" => Closure(object $proxy, LogManager $realInstance, string $method, array $parameters, &$returnValue, bool &$overrideReturnValue) {#278 ▶}
  ]
}
"Before executing the error log method."
"After executing the error log method."

Order

 $ php artisan proxy:list
$ php artisan proxy:clear
 ╰─ php artisan proxy:list                                                                                       ─╯
+-------+---------------------------+-------------------------------------------+---------------------------------+
| Index | Original Class            | Proxy Class                               | Proxy Type                      |
+-------+---------------------------+-------------------------------------------+---------------------------------+
| 1     | App\Foo                   | Generated5320f6306ba550844e07c949e4af382d | Virtual Proxy                   |
| 2     | Illuminate\Log\LogManager | Generated9b66c8f3bc457c2c26acc55874d391b3 | Access Interceptor Value Holder |
+-------+---------------------------+-------------------------------------------+---------------------------------+

Reference link

Original link


guanguans
2.4k 声望89 粉丝

No practice, no gain in one's wit.