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获取网页中图片、DIV内容的简单方法
Jun 19 PHP
Thinkphp中volist标签mod控制一定记录的换行BUG解决方法
Nov 04 PHP
php仿微信红包分配算法的实现方法
May 13 PHP
mysql alter table命令修改表结构实例详解
Sep 24 PHP
Python中使用django form表单验证的方法
Jan 16 PHP
thinkphp3.2嵌入百度编辑器ueditor的实例代码
Jul 13 PHP
laravel自定义分页效果
Jul 23 PHP
PHP 应用容器化以及部署方法
Feb 12 PHP
PHP正则表达式处理函数(PCRE 函数)实例小结
May 09 PHP
Laravel 微信小程序后端搭建步骤详解
Nov 26 PHP
php实现根据身份证获取精准年龄
Feb 26 PHP
php远程请求CURL实例教程(爬虫、保存登录状态)
Dec 10 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
如何在PHP中使用Oracle数据库(4)
2006/10/09 PHP
php cookie 作用范围?不要在当前页面使用你的cookie
2009/03/24 PHP
Thinkphp5结合layer弹窗定制操作结果页面
2017/07/07 PHP
数组Array进行原型prototype扩展后带来的for in遍历问题
2010/02/07 Javascript
用js实现计算加载页面所用的时间
2010/04/02 Javascript
jQuery + Flex 通过拖拽方式动态改变图片的代码
2011/08/03 Javascript
JavaScript高级程序设计 错误处理与调试学习笔记
2011/09/10 Javascript
jQuery中对未来的元素绑定事件用bind、live or on
2014/04/17 Javascript
JavaScript操作HTML元素和样式的方法详解
2015/10/21 Javascript
Bootstrap每天必学之按钮(一)
2015/11/24 Javascript
Jquery 1.9.1源码分析系列(十二)之筛选操作
2015/12/02 Javascript
jQuery插件echarts实现的循环生成图效果示例【附demo源码下载】
2017/03/04 Javascript
微信小程序视图template模板引用的实例详解
2017/09/20 Javascript
解析Json字符串的三种方法日常常用
2018/05/02 Javascript
解决vue的router组件component在import时不能使用变量问题
2020/07/26 Javascript
element 动态合并表格的步骤
2020/12/31 Javascript
Python实现的简单万年历例子分享
2014/04/25 Python
python使用Berkeley DB数据库实例
2014/09/26 Python
Python编程之多态用法实例详解
2015/05/19 Python
Python中的模块导入和读取键盘输入的方法
2015/10/16 Python
python+django+sql学生信息管理后台开发
2018/01/11 Python
Python实现的连接mssql数据库操作示例
2018/08/17 Python
实时获取Python的print输出流方法
2019/01/07 Python
基于pygame实现童年掌机打砖块游戏
2020/02/25 Python
HTML5自定义data-* data(obj)属性和jquery的data()方法的使用
2012/12/13 HTML / CSS
印度排名第一的蛋糕、鲜花和礼品送货:Winni
2019/08/02 全球购物
数控机械专业个人的自我评价
2014/01/02 职场文书
好邻里事迹材料
2014/01/16 职场文书
员工试用期考核自我鉴定
2014/04/13 职场文书
访谈节目策划方案
2014/05/15 职场文书
音乐幼师求职信
2014/07/09 职场文书
领导班子个人对照检查剖析材料
2014/09/29 职场文书
申报优秀教师材料
2014/12/16 职场文书
gateway与spring-boot-starter-web冲突问题的解决
2021/07/16 Java/Android
SQL实现LeetCode(180.连续的数字)
2021/08/04 MySQL
Springboot集成kafka高级应用实战分享
2022/08/14 Java/Android