Laravel源码解析之路由的使用和示例详解


Posted in PHP onSeptember 27, 2018

前言

我的解析文章并非深层次多领域的解析攻略。但是参考着开发文档看此类文章会让你在日常开发中更上一层楼。

废话不多说,我们开始本章的讲解。

入口

Laravel启动后,会先加载服务提供者、中间件等组件,在查找路由之前因为我们使用的是门面,所以先要查到Route的实体类。

注册

第一步当然还是通过服务提供者,因为这是laravel启动的关键,在 RouteServiceProvider 内加载路由文件。

protected function mapApiRoutes()
{
  Route::prefix('api')
     ->middleware('api')
     ->namespace($this->namespace) // 设置所处命名空间
     ->group(base_path('routes/api.php')); //所得路由文件绝对路径
}

首先require是不可缺少的。因路由文件中没有命名空间。 Illuminate\Routing\Router 下方法

protected function loadRoutes($routes)
{
  if ($routes instanceof Closure) {
    $routes($this);
  } else {
    $router = $this;

    require $routes;
  }
}

随后通过路由找到指定方法,依旧是 Illuminate\Routing\Router 内有你所使用的所有路由相关方法,例如get、post、put、patch等等,他们都调用了统一的方法 addRoute

public function addRoute($methods, $uri, $action)
{
  return $this->routes->add($this->createRoute($methods, $uri, $action));
}

之后通过 Illuminate\Routing\RouteCollection addToCollections 方法添加到集合中

protected function addToCollections($route)
{
  $domainAndUri = $route->getDomain().$route->uri();

  foreach ($route->methods() as $method) {
    $this->routes[$method][$domainAndUri] = $route;
  }

  $this->allRoutes[$method.$domainAndUri] = $route;
}

添加后的结果如下图所示

Laravel源码解析之路由的使用和示例详解

实例化

依旧通过反射加载路由指定的控制器,这个时候build的参数$concrete = App\Api\Controllers\XxxController

public function build($concrete)
{
  // If the concrete type is actually a Closure, we will just execute it and
  // hand back the results of the functions, which allows functions to be
  // used as resolvers for more fine-tuned resolution of these objects.
  if ($concrete instanceof Closure) {
    return $concrete($this, $this->getLastParameterOverride());
  }
  
  $reflector = new ReflectionClass($concrete);
  // If the type is not instantiable, the developer is attempting to resolve
  // an abstract type such as an Interface of Abstract Class and there is
  // no binding registered for the abstractions so we need to bail out.
  if (! $reflector->isInstantiable()) {
    return $this->notInstantiable($concrete);
  }
  
    
  $this->buildStack[] = $concrete;

  $constructor = $reflector->getConstructor();
  // If there are no constructors, that means there are no dependencies then
  // we can just resolve the instances of the objects right away, without
  // resolving any other types or dependencies out of these containers.
  if (is_null($constructor)) {
  
      array_pop($this->buildStack);
  
      return new $concrete;
  }

  $dependencies = $constructor->getParameters();
  // Once we have all the constructor's parameters we can create each of the
  // dependency instances and then use the reflection instances to make a
  // new instance of this class, injecting the created dependencies in.
  $instances = $this->resolveDependencies(
    $dependencies
  );

  array_pop($this->buildStack);
  
  return $reflector->newInstanceArgs($instances);
}

这时将返回控制器的实例,下面将通过url访问指定方法,一般控制器都会继承父类 Illuminate\Routing\Controller ,laravel为其设置了别名 BaseController

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));
}

Laravel通过controller继承的callAction去调用子类的指定方法,也就是我们希望调用的自定义方法。

public function callAction($method, $parameters)
{
  return call_user_func_array([$this, $method], $parameters);
}

致谢

感谢你看到这里,本篇文章源码解析靠个人理解。如有出入请拍砖。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

PHP 相关文章推荐
PHP Token(令牌)设计
Mar 15 PHP
php快速url重写 更新版[需php 5.30以上]
Apr 20 PHP
供参考的 php 学习提高路线分享
Oct 23 PHP
注意:php5.4删除了session_unregister函数
Aug 05 PHP
PHP中session变量的销毁
Feb 27 PHP
Yii中render和renderPartial的区别
Sep 03 PHP
PHP实现中国公民身份证号码有效性验证示例代码
May 03 PHP
PHP实现从PostgreSQL数据库检索数据分页显示及根据条件查找数据示例
Jun 09 PHP
php PDO属性设置与操作方法分析
Dec 27 PHP
详解php中curl返回false的解决办法
Mar 18 PHP
PHP生成短网址的思路以及实现方法的详解
Mar 25 PHP
php pdo连接数据库操作示例
Nov 18 PHP
php实现有序数组旋转后寻找最小值方法
Sep 27 #PHP
PHP实现SMTP邮件的发送实例
Sep 27 #PHP
ThinkPHP like模糊查询,like多匹配查询,between查询,in查询,一般查询书写方法
Sep 26 #PHP
thinkPHP利用ajax异步上传图片并显示、删除的示例
Sep 26 #PHP
多个Laravel项目如何共用migrations详解
Sep 25 #PHP
php中上传文件的的解决方案
Sep 25 #PHP
PHP调用微博接口实现微博登录的方法示例
Sep 22 #PHP
You might like
全国FM电台频率大全 - 10 江苏省
2020/03/11 无线电
PHP中上传大体积文件时需要的设置
2006/10/09 PHP
一步一步学习PHP(2)――PHP类型
2010/02/15 PHP
PHP处理postfix邮件内容的方法
2015/06/16 PHP
php通过两层过滤获取留言内容的方法
2016/07/11 PHP
学习jquery必备 api中英文对照的chm手册 下载
2007/05/03 Javascript
jquery移动listbox的值原理及代码
2013/05/03 Javascript
JS修改css样式style浅谈
2013/05/06 Javascript
div当滚动到页面顶部的时候固定在顶部实例代码
2013/05/27 Javascript
谈谈impress.js初步理解
2015/09/09 Javascript
基于javascript实现泡泡大冒险网页版小游戏
2016/03/23 Javascript
Node.js用readline模块实现输入输出
2016/12/16 Javascript
jsonp跨域请求实现示例
2017/03/13 Javascript
Vue DevTools调试工具的使用
2017/12/05 Javascript
JavaScript实现二叉树定义、遍历及查找的方法详解
2017/12/20 Javascript
Vue 拦截器对token过期处理方法
2018/01/23 Javascript
浅谈es6中export和export default的作用及区别
2018/02/07 Javascript
如何更好的编写js async函数
2018/05/13 Javascript
浅谈angular表单提交中ng-submit的默认使用方法
2018/09/30 Javascript
初学vue出现空格警告的原因及其解决方案
2019/10/31 Javascript
JavaScript/TypeScript 实现并发请求控制的示例代码
2021/01/18 Javascript
[39:08]完美世界DOTA2联赛PWL S3 LBZS vs CPG 第一场 12.12
2020/12/16 DOTA
Pycharm编辑器技巧之自动导入模块详解
2017/07/18 Python
Python3标准库总结
2019/02/19 Python
pycharm new project变成灰色的解决方法
2019/06/27 Python
python下载库的步骤方法
2019/10/12 Python
Virtualenv 搭建 Py项目运行环境的教程详解
2020/06/22 Python
通俗讲解python 装饰器
2020/09/07 Python
利用CSS3实现平移动画效果示例代码
2016/10/12 HTML / CSS
一款html5 canvas实现的图片玻璃碎片特效
2014/09/11 HTML / CSS
美国著名的团购网站:Woot
2016/08/02 全球购物
override和overload的区别
2016/03/09 面试题
学校爱国卫生月活动总结
2014/06/25 职场文书
党政领导班子群众路线对照检查材料
2014/10/26 职场文书
《这片土地是神圣的》教学反思
2016/02/16 职场文书
甜美蛋糕店的创业计划书模板,拿来即用!
2019/08/21 职场文书