delegate.class.php 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186
  1. <?php
  2. require_once dirname(__FILE__, 3) . '/vendor/autoload.php';
  3. /**
  4. * ZenTaoPHP 的第三方类库代理类,将方法调用委托给实例或静态类。
  5. * ZenTaoPHP's third-party library proxy class delegates method calls to an instance or a static class.
  6. *
  7. * 代理类的子类可以通过继承 baseDelegate 类来实现对第三方类库的调用。
  8. * Subclasses of the proxy class can call third-party libraries by inheriting the baseDelegate class.
  9. *
  10. * 代理类的子类需要定义一个静态属性 className 来指定要调用的第三方类库的类名。
  11. * The subclass of the proxy class needs to define a static property className to specify the class name of the third-party library to be called.
  12. *
  13. * 代理类的子类还需要在构造函数中初始化一个实例属性 instance 来保存第三方类库的实例。
  14. * The subclass of the proxy class also needs to initialize an instance property instance in the constructor to save the instance of the third-party library.
  15. *
  16. * 例如:
  17. * For example:
  18. * class myLib extends baseDelegate
  19. * {
  20. * protected static $className = 'ThirdPartyClass';
  21. * public function __construct()
  22. * {
  23. * $this->instance = new static::$className();
  24. * }
  25. * }
  26. *
  27. * 这样就可以通过 myLib 类来调用 ThirdPartyClass 类的方法了。
  28. * In this way, you can call the methods of the ThirdPartyClass class through the myLib class.
  29. */
  30. class baseDelegate
  31. {
  32. /**
  33. * 第三方类库的实例
  34. * Instance of the third-party library
  35. *
  36. * @var object
  37. * @access protected
  38. */
  39. protected $instance = null;
  40. /**
  41. * 代理对实例属性的读取。
  42. * 当访问一个不存在的属性时,尝试从实例中获取。
  43. *
  44. * @param string $name 属性名
  45. * @return mixed
  46. * @throws Error 如果属性不存在
  47. */
  48. public function __get($name)
  49. {
  50. // 如果有实例,尝试从实例中获取属性
  51. if(!is_null($this->instance) && property_exists($this->instance, $name))
  52. {
  53. return $this->instance->$name;
  54. }
  55. // 如果找不到,抛出错误
  56. $calledClass = get_called_class();
  57. throw new Error("Access to undeclared property: {$calledClass}::\${$name}");
  58. }
  59. /**
  60. * 代理对实例属性的写入。
  61. * 当写入一个不存在的属性时,尝试写入实例中。
  62. *
  63. * @param string $name 属性名
  64. * @param mixed $value 值
  65. * @return void
  66. * @throws Error 如果属性不存在
  67. */
  68. public function __set($name, $value)
  69. {
  70. // 如果有实例,尝试写入实例属性
  71. if(!is_null($this->instance) && property_exists($this->instance, $name))
  72. {
  73. $this->instance->$name = $value;
  74. return;
  75. }
  76. // 如果找不到,抛出错误
  77. $calledClass = get_called_class();
  78. throw new Error("Cannot set undeclared property: {$calledClass}::\${$name}");
  79. }
  80. /**
  81. * 调用实例方法
  82. * Call instance methods
  83. *
  84. * @param string $name 方法名 Method name
  85. * @param array $arguments 方法参数 Method arguments
  86. * @return mixed
  87. * @throws BadMethodCallException 如果实例未初始化或方法不存在 If the instance is not initialized or the method does not exist
  88. */
  89. public function __call($name, $arguments)
  90. {
  91. if(is_null($this->instance))
  92. {
  93. throw new BadMethodCallException('The instance is not initialized.');
  94. }
  95. if(is_callable([$this->instance, $name]))
  96. {
  97. return call_user_func_array([$this->instance, $name], $arguments);
  98. }
  99. $calledClass = get_called_class();
  100. throw new BadMethodCallException("The method {$name} does not exist in the class {$calledClass}.");
  101. }
  102. /**
  103. * 调用静态方法
  104. * Call static methods
  105. *
  106. * @param string $name 方法名 Method name
  107. * @param array $arguments 方法参数 Method arguments
  108. * @return mixed
  109. * @throws BadMethodCallException 如果类名未设置或类不存在或方法不存在 If the class name is not set or the class does not exist or the method does not exist
  110. */
  111. public static function __callStatic($name, $arguments)
  112. {
  113. $calledClass = get_called_class();
  114. if(!property_exists($calledClass, 'className'))
  115. {
  116. throw new BadMethodCallException("The static property className does not exist in the class {$calledClass}.");
  117. }
  118. $className = $calledClass::$className;
  119. if(empty($className))
  120. {
  121. throw new BadMethodCallException("The static property className is not set in the class {$calledClass}.");
  122. }
  123. if(!class_exists($className))
  124. {
  125. throw new BadMethodCallException("The class {$className} does not exist.");
  126. }
  127. if(is_callable([$className, $name]))
  128. {
  129. return call_user_func_array([$className, $name], $arguments);
  130. }
  131. $argumentCount = count($arguments);
  132. if(property_exists($className, $name) && $argumentCount === 1)
  133. {
  134. // 支持静态属性的直接赋值
  135. $className::$$name = $arguments[0];
  136. return;
  137. }
  138. if(property_exists($className, $name) && $argumentCount === 0)
  139. {
  140. // 支持静态属性的直接读取
  141. return $className::$$name;
  142. }
  143. if(strpos($name, 'set') === 0 && property_exists($className, lcfirst(substr($name, 3))) && $argumentCount === 1)
  144. {
  145. // 支持静态属性的 set 方法
  146. $property = lcfirst(substr($name, 3));
  147. $className::$$property = $arguments[0];
  148. return;
  149. }
  150. if(strpos($name, 'get') === 0 && property_exists($className, lcfirst(substr($name, 3))) && $argumentCount === 0)
  151. {
  152. // 支持静态属性的 get 方法
  153. $property = lcfirst(substr($name, 3));
  154. return $className::$$property;
  155. }
  156. throw new BadMethodCallException("The method {$name} does not exist in the class {$calledClass}.");
  157. }
  158. /**
  159. * 获取第三方类库的实例
  160. * Get the instance of the third-party library
  161. *
  162. * @access public
  163. * @return mixed
  164. */
  165. public function getInstance()
  166. {
  167. return $this->instance;
  168. }
  169. }