资讯专栏INFORMATION COLUMN

Laravel 路由执行

luoyibu / 338人阅读

摘要:路由执行代码展示控制器形式匿名函数形式控制器形式处理控制器参数解析返回过滤的从路径或主机名解析出来的对应的参数数组,类似方式调用控制器的方法可以有自己的区别于路由参数的

Laravel 路由执行 代码展示
protected function runRouteWithinStack(Route $route, Request $request)
{
    $shouldSkipMiddleware = $this->container->bound("middleware.disable") &&
                            $this->container->make("middleware.disable") === true;

    $middleware = $shouldSkipMiddleware ? [] : $this->gatherRouteMiddleware($route);

    return (new Pipeline($this->container))
                    ->send($request)
                    ->through($middleware)
                    ->then(function ($request) use ($route) {
                        return $this->prepareResponse(
                            $request, $route->run()
                        );
                    });
}

public function run()
{
    $this->container = $this->container ?: new Container;

    try {
        // 控制器形式(Controller@Method)
        if ($this->isControllerAction()) {
            return $this->runController();
        }
        // 匿名函数形式
        return $this->runCallable();
    } catch (HttpResponseException $e) {
        return $e->getResponse();
    }
}
控制器形式处理
protected function runController()
{
    return (new ControllerDispatcher($this->container))->dispatch(
        $this, $this->getController(), $this->getControllerMethod()
    );
}
public function getController()
{
    $class = $this->parseControllerCallback()[0];

    if (! $this->controller) {
        $this->controller = $this->container->make($class);
    }

    return $this->controller;
}
protected function getControllerMethod()
{
    return $this->parseControllerCallback()[1];
}
protected function parseControllerCallback()
{
    return Str::parseCallback($this->action["uses"]);
}
public static function parseCallback($callback, $default = null)
{
    return static::contains($callback, "@") ? explode("@", $callback, 2) : [$callback, $default];
}
// IlluminateRoutingControllerDispatcher
public function __construct(Container $container)
{
    $this->container = $container;
}
public function dispatch(Route $route, $controller, $method)
{
    // 控制器参数解析
    $parameters = $this->resolveClassMethodDependencies(
        $route->parametersWithoutNulls(), $controller, $method
    );

    if (method_exists($controller, "callAction")) {
        return $controller->callAction($method, $parameters);
    }

    return $controller->{$method}(...array_values($parameters));
}
public function parametersWithoutNulls()
{
    // 返回过滤的从路径或主机名解析出来的对应的参数数组,类似 ["post"=>1,"comment"=>2]
    return array_filter($this->parameters(), function ($p) {
        return ! is_null($p);
    });
}
protected function resolveClassMethodDependencies(array $parameters, $instance, $method)
{
    // __invoke 方式调用
    if (! method_exists($instance, $method)) {
        return $parameters;
    }

    return $this->resolveMethodDependencies(
        $parameters, new ReflectionMethod($instance, $method)
    );
}
// 控制器的方法可以有自己的区别于路由参数的类类型参数,其他参数只能从路由获取
public function resolveMethodDependencies(array $parameters, ReflectionFunctionAbstract $reflector)
{
    $results = [];

    $instanceCount = 0;

    $values = array_values($parameters);
    
    foreach ($reflector->getParameters() as $key => $parameter) {
        // 类方法自己的类类型参数,尝试实例化
        $instance = $this->transformDependency(
            $parameter, $parameters
        );
        
        if (! is_null($instance)) {
            $instanceCount++;

            $results[] = $instance;
        } else {    // 按照类方法的参数顺序依次存放数据
            $results[] = isset($values[$key - $instanceCount])
                ? $values[$key - $instanceCount] : $parameter->getDefaultValue();
        }
    }

    return $results;
}
protected function transformDependency(ReflectionParameter $parameter, $parameters)
{
    $class = $parameter->getClass();
    // 类类型且没有实例化,则通过服务容器解决参数的依赖关系,并进行实例化
    if ($class && ! $this->alreadyInParameters($class->name, $parameters)) {
        return $this->container->make($class->name);
    }
}
protected function alreadyInParameters($class, array $parameters)
{
    return ! is_null(Arr::first($parameters, function ($value) use ($class) {
        return $value instanceof $class;
    }));
}
public function callAction($method, $parameters)
{
    return call_user_func_array([$this, $method], $parameters);
}

小结:
主要就是将路由获取到的参数依次对应到控制器方法的参数,当然控制器方法可以有自己的类类型参数

匿名函数形式处理
protected function runCallable()
{
    $callable = $this->action["uses"];
    // 一样的处理方式
    return $callable(...array_values($this->resolveMethodDependencies(
        $this->parametersWithoutNulls(), new ReflectionFunction($this->action["uses"])
    )));
}
返回

即控制器的返回

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/22613.html

相关文章

  • 【日常填坑】之ajax请求laravel的api接口

    摘要:合适和够用是最完美的追求。比如从页面去请求的资源。它允许浏览器向跨源服务器,发出请求,从而克服了只能同源使用的限制。定义在中的路由都是无状态的,并且会应用中间件组。 关于作者 程序开发人员,不拘泥于语言与技术,目前主要从事PHP和前端开发,使用Laravel和VueJs,App端使用Apicloud混合式开发。合适和够用是最完美的追求。 个人网站:http://www.linganm...

    Arno 评论0 收藏0
  • 【日常填坑】之ajax请求laravel的api接口

    摘要:合适和够用是最完美的追求。比如从页面去请求的资源。它允许浏览器向跨源服务器,发出请求,从而克服了只能同源使用的限制。定义在中的路由都是无状态的,并且会应用中间件组。 关于作者 程序开发人员,不拘泥于语言与技术,目前主要从事PHP和前端开发,使用Laravel和VueJs,App端使用Apicloud混合式开发。合适和够用是最完美的追求。 个人网站:http://www.linganm...

    neu 评论0 收藏0
  • 【日常填坑】之ajax请求laravel的api接口

    摘要:合适和够用是最完美的追求。比如从页面去请求的资源。它允许浏览器向跨源服务器,发出请求,从而克服了只能同源使用的限制。定义在中的路由都是无状态的,并且会应用中间件组。 关于作者 程序开发人员,不拘泥于语言与技术,目前主要从事PHP和前端开发,使用Laravel和VueJs,App端使用Apicloud混合式开发。合适和够用是最完美的追求。 个人网站:http://www.linganm...

    fuyi501 评论0 收藏0
  • 「新轮子」PHP CORS (Cross-origin resource sharing),解决 P

    摘要:而我的新轮子也并不是专门解决它的问题的,而是顺便解决而已。概述这个包,支持在所有的项目中使用。一旦出现成员,代表允许全部。列出允许跨域请求的方法列表,默认是代表所有方法。信息地址嗯,新轮子,求一波。 showImg(https://segmentfault.com/img/bV5VxN?w=844&h=656); 是的,可能了解 Laravel 的都知道,在 Laravel 中简单的设...

    lbool 评论0 收藏0
  • 刚接触一个 Laravel 项目,你可以从这些地方入手

    摘要:在每一个的项目主页上,展示了扩展包的介绍版本号仓库地址如完整的文件,以及其他一些有用的信息。官方文档给出了总结服务提供者是所有应用程序引导中心。你可以浏览位于目录下的所有应用程序服务提供者。 showImg(https://segmentfault.com/img/bV6vPF?w=1200&h=500); 当你接手一个新项目的时候,可能会感到无从下手,如果不熟悉编程,则更是如此。那么...

    RyanQ 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<