[PHP] 纯文本查看 复制代码public function invokeMethod($method, array $vars = [], bool $accessible = false)
{
if (is_array($method)) {
[$class, $method] = $method;
$class = is_object($class) ? $class : $this->invokeClass($class);
} else {
// 静态方法
[$class, $method] = explode('::', $method);
}
try {
$reflect = new ReflectionMethod($class, $method);
} catch (ReflectionException $e) {
$class = is_object($class) ? get_class($class) : $class;
throw new FuncNotFoundException('method not exists: ' . $class . '::' . $method . '()', "{$class}::{$method}", $e);
}
$args = $this->bindParams($reflect, $vars);
if ($accessible) {
$reflect->setAccessible($accessible);
}
return $reflect->invokeArgs(is_object($class) ? $class : null, $args);
}
/**
* 调用反射执行类的方法 支持参数绑定
* [url=home.php?mod=space&uid=718080]@access[/url] public
* @param object $instance 对象实例
* @param mixed $reflect 反射类
* @param array $vars 参数
* @return mixed
*/
public function invokeReflectMethod($instance, $reflect, array $vars = [])
{
$args = $this->bindParams($reflect, $vars);
return $reflect->invokeArgs($instance, $args);
}
/**
* 调用反射执行callable 支持参数绑定
* @access public
* @param mixed $callable
* @param array $vars 参数
* @param bool $accessible 设置是否可访问
* @return mixed
*/
public function invoke($callable, array $vars = [], bool $accessible = false)
{
if ($callable instanceof Closure) {
return $this->invokeFunction($callable, $vars);
} elseif (is_string($callable) && false === strpos($callable, '::')) {
return $this->invokeFunction($callable, $vars);
} else {
return $this->invokeMethod($callable, $vars, $accessible);
}
}
/**
* 调用反射执行类的实例化 支持依赖注入
* @access public
* @param string $class 类名
* @param array $vars 参数
* @return mixed
*/
public function invokeClass(string $class, array $vars = [])
{
try {
$reflect = new ReflectionClass($class);
} catch (ReflectionException $e) {
throw new ClassNotFoundException('class not exists: ' . $class, $class, $e);
}
if ($reflect->hasMethod('__make')) {
$method = $reflect->getMethod('__make');
if ($method->isPublic() && $method->isStatic()) {
$args = $this->bindParams($method, $vars);
return $method->invokeArgs(null, $args);
}
}
$constructor = $reflect->getConstructor();
$args = $constructor ? $this->bindParams($constructor, $vars) : [];
$object = $reflect->newInstanceArgs($args);
$this->invokeAfter($class, $object);
return $object;
}
/**
* 执行invokeClass回调
* @access protected
* @param string $class 对象类名
* @param object $object 容器对象实例
* @return void
*/
protected function invokeAfter(string $class, $object): void
{
if (isset($this->invokeCallback['*'])) {
foreach ($this->invokeCallback['*'] as $callback) {
$callback($object, $this);
}
}
if (isset($this->invokeCallback[$class])) {
foreach ($this->invokeCallback[$class] as $callback) {
$callback($object, $this);
}
}
}
/**
* 绑定参数
* @access protected
* @param ReflectionFunctionAbstract $reflect 反射类
* @param array $vars 参数
* @return array
*/
protected function bindParams(ReflectionFunctionAbstract $reflect, array $vars = []): array
{
if ($reflect->getNumberOfParameters() == 0) {
return [];
}
// 判断数组类型 数字数组时按顺序绑定参数
reset($vars);
$type = key($vars) === 0 ? 1 : 0;
$params = $reflect->getParameters();
$args = [];
foreach ($params as $param) {
$name = $param->getName();
$lowerName = Str::snake($name);
$class = $param->getClass();
if ($class) {
$args[] = $this->getObjectParam($class->getName(), $vars);
} elseif (1 == $type && !empty($vars)) {
$args[] = array_shift($vars);
} elseif (0 == $type && isset($vars[$name])) {
$args[] = $vars[$name];
} elseif (0 == $type && isset($vars[$lowerName])) {
$args[] = $vars[$lowerName];
} elseif ($param->isDefaultValueAvailable()) {
$args[] = $param->getDefaultValue();
} else {
throw new InvalidArgumentException('method param miss:' . $name);
}
}
return $args;
}
/**
* 创建工厂对象实例
* @param string $name 工厂类名
* @param string $namespace 默认命名空间
* @param array $args
* @return mixed
* @deprecated
* @access public
*/
public static function factory(string $name, string $namespace = '', ...$args)
{
$class = false !== strpos($name, '\\') ? $name : $namespace . ucwords($name);
return Container::getInstance()->invokeClass($class, $args);
}
/**
* 获取对象类型的参数值
* @access protected
* @param string $className 类名
* @param array $vars 参数
* @return mixed
*/
protected function getObjectParam(string $className, array &$vars)
{
$array = $vars;
$value = array_shift($array);
if ($value instanceof $className) {
$result = $value;
array_shift($vars);
} else {
$result = $this->make($className);
}
return $result;
}
public function __set($name, $value)
{
$this->bind($name, $value);
}
public function __get($name)
{
return $this->get($name);
}
public function __isset($name): bool
{
return $this->exists($name);
}
public function __unset($name)
{
$this->delete($name);
}
public function offsetExists($key)
{
return $this->exists($key);
}
public function offsetGet($key)
{
return $this->make($key);
}
public function offsetSet($key, $value)
{
$this->bind($key, $value);
}
public function offsetUnset($key)
{
$this->delete($key);
}
//Countable
public function count()
{
return count($this->instances);
}
//IteratorAggregate
public function getIterator()
{
return new ArrayIterator($this->instances);
}
}