Laravel 源码方法执行类详细分析

前言 单纯为了学习

Illuminate\Container\BoundMethod分析

1. 引入

use Closure;//匿名函数
use ReflectionMethod;//反射类
use ReflectionFunction;//报告一个函数的有关信息
use InvalidArgumentException;//参数异常类

2. 调用给定的方法并注入其依赖项

1、isCallableWithAtSign
2、callClass
3、callBoundMethod
4、getMethodDependencies

 public static function call($container, $callback, array $parameters = [], $defaultMethod = null)
    {
        //判断$callback是否在Class@method语法中 或者 有默认的方法名
        if (static::isCallableWithAtSign($callback) || $defaultMethod) {
            return static::callClass($container, $callback, $parameters, $defaultMethod);
        }

        //执行方法
        return static::callBoundMethod($container, $callback, function () use ($container, $callback, $parameters) {
            return call_user_func_array(
                $callback, static::getMethodDependencies($container, $callback, $parameters)//
            );
        });
    }

3. 使用Class@method语法调用对类的字符串引用

    protected static function callClass($container, $target, array $parameters = [], $defaultMethod = null)
    {
        $segments = explode('@', $target);//按@字符分割callback
        $method = count($segments) === 2? $segments[1] : $defaultMethod;//获取方法名
        if (is_null($method)) {
            throw new InvalidArgumentException('Method not provided.');//为空的话抛出异常
        }
       //直接传回依赖项绑定的“call”方法。
        return static::call(
            $container, [$container->make($segments[0]), $method], $parameters
        );
    }

4. 调用绑定到容器的方法

    protected static function callBoundMethod($container, $callback, $default)
    {
        //判断如果callback不是数组
        if (! is_array($callback)) {
            return $default instanceof Closure ? $default() : $default;//如果default是匿名函数就调取否则返回
        }
        //序列化方法名 class@method
        $method = static::normalizeMethod($callback);
        //检测容器是否有给定的方法绑定
        if ($container->hasMethodBinding($method)) {
            return $container->callMethodBinding($method, $callback[0]);//立即执行容器绑定方法
        }
        return $default instanceof Closure ? $default() : $default;//如果default是匿名函数就调取否则返回
    }

5. 序列化方法名

 protected static function normalizeMethod($callback)
    {
        $class = is_string($callback[0]) ? $callback[0] : get_class($callback[0]);

        return "{$class}@{$callback[1]}";
    }

6. 获取给定发放的所有依赖项

1、getCallReflector
2、addDependencyForCallParameter

protected static function getMethodDependencies($container, $callback, array $parameters = [])
    {
        $dependencies = [];
        //获取反射实例->获取参数
        foreach (static::getCallReflector($callback)->getParameters() as $parameter) {
            static::addDependencyForCallParameter($container, $parameter, $parameters, $dependencies);//获取依赖项
        }
        return array_merge($dependencies, $parameters);
    }

7. 获取给定回调的反射实例

protected static function getCallReflector($callback)
    {
        if (is_string($callback) && strpos($callback, '::') !== false) {
            $callback = explode('::', $callback);
        }

        return is_array($callback)
                        ? new ReflectionMethod($callback[0], $callback[1])
                        : new ReflectionFunction($callback);
    }

8. 获取给定调用参数的依赖项

    protected static function addDependencyForCallParameter($container, $parameter, array &$parameters, &$dependencies)
    {
        //判断参数名是否已存在传入的参数数组
        if (array_key_exists($parameter->name, $parameters)) {
            $dependencies[] = $parameters[$parameter->name];//加入依赖项数组
            unset($parameters[$parameter->name]);//释放参数数组
        } 
        elseif ($parameter->getClass() && array_key_exists($parameter->getClass()->name, $parameters)) {
            $dependencies[] = $parameters[$parameter->getClass()->name];

            unset($parameters[$parameter->getClass()->name]);
        } elseif ($parameter->getClass()) {
            $dependencies[] = $container->make($parameter->getClass()->name);
        } elseif ($parameter->isDefaultValueAvailable()) {
            $dependencies[] = $parameter->getDefaultValue();
        }
    }

9. 确定给定的字符串是否在Class@method语法中

protected static function isCallableWithAtSign($callback)
    {
        return is_string($callback) && strpos($callback, '@') !== false;
    }
本作品采用《CC 协议》,转载必须注明作者和本文链接
《L05 电商实战》
从零开发一个电商项目,功能包括电商后台、商品 & SKU 管理、购物车、订单管理、支付宝支付、微信支付、订单退款流程、优惠券等
《L03 构架 API 服务器》
你将学到如 RESTFul 设计风格、PostMan 的使用、OAuth 流程,JWT 概念及使用 和 API 开发相关的进阶知识。
讨论数量: 0
(= ̄ω ̄=)··· 暂无内容!

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!