Proxy.php 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384
  1. <?php
  2. namespace think\swoole\rpc\client;
  3. use InvalidArgumentException;
  4. use Nette\PhpGenerator\Factory;
  5. use Nette\PhpGenerator\PhpNamespace;
  6. use ReflectionClass;
  7. use think\App;
  8. use think\swoole\Middleware;
  9. use think\swoole\rpc\Protocol;
  10. abstract class Proxy
  11. {
  12. protected $interface;
  13. /** @var Gateway */
  14. protected $gateway;
  15. /** @var App */
  16. protected $app;
  17. protected $middleware = [];
  18. final public function __construct(App $app, Gateway $gateway, $middleware)
  19. {
  20. $this->app = $app;
  21. $this->gateway = $gateway;
  22. $this->middleware = $middleware;
  23. }
  24. final protected function proxyCall($method, $params)
  25. {
  26. $protocol = Protocol::make($this->interface, $method, $params);
  27. return Middleware::make($this->app, $this->middleware)
  28. ->pipeline()
  29. ->send($protocol)
  30. ->then(function (Protocol $protocol) {
  31. return $this->gateway->call($protocol);
  32. });
  33. }
  34. final public static function getClassName($client, $interface)
  35. {
  36. if (!interface_exists($interface)) {
  37. throw new InvalidArgumentException(
  38. sprintf('%s must be exist interface!', $interface)
  39. );
  40. }
  41. $proxyName = class_basename($interface) . "Service";
  42. $className = "rpc\\service\\{$client}\\{$proxyName}";
  43. if (!class_exists($className, false)) {
  44. $namespace = new PhpNamespace("rpc\\service\\{$client}");
  45. $namespace->addUse(Proxy::class);
  46. $namespace->addUse($interface);
  47. $class = $namespace->addClass($proxyName);
  48. $class->setExtends(Proxy::class);
  49. $class->addImplement($interface);
  50. $class->addProperty('interface', class_basename($interface));
  51. $reflection = new ReflectionClass($interface);
  52. foreach ($reflection->getMethods() as $methodRef) {
  53. $method = (new Factory)->fromMethodReflection($methodRef);
  54. $body = "\$this->proxyCall('{$methodRef->getName()}', func_get_args());";
  55. if ($method->getReturnType() != 'void') {
  56. $body = "return {$body}";
  57. }
  58. $method->setBody($body);
  59. $class->addMember($method);
  60. }
  61. eval($namespace);
  62. }
  63. return $className;
  64. }
  65. }