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对MongoDB[NoSQL]数据库的操作
Mar 01 PHP
ThinkPHP多语言支持与多模板支持概述
Aug 22 PHP
Yii框架获取当前controlle和action对应id的方法
Dec 03 PHP
php根据某字段对多维数组进行排序的方法
Mar 07 PHP
php实现以只读方式打开文件的方法
Mar 16 PHP
3种php生成唯一id的方法
Nov 23 PHP
PHP读取PPT文件的方法
Dec 10 PHP
yii2中添加验证码的实现方法
Jan 09 PHP
php自定义函数实现JS的escape的方法示例
Jul 07 PHP
Laravel 5使用Laravel Excel实现Excel/CSV文件导入导出的功能详解
Oct 11 PHP
基于PHP实现的多元线性回归模拟曲线算法
Jan 30 PHP
laravel项目利用twemproxy部署redis集群的完整步骤
May 11 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
mysql 字段类型说明
2007/04/27 PHP
PHP时间和日期函数详解
2015/05/08 PHP
PHP根据树的前序遍历和中序遍历构造树并输出后序遍历的方法
2017/11/10 PHP
繁简字转换功能
2006/07/19 Javascript
javascript之大字符串的连接的StringBuffer 类
2007/05/08 Javascript
jquery jqPlot API 中文使用教程(非常强大的图表工具)
2011/08/15 Javascript
Extjs4中Form的使用之本地hiddenfield
2013/11/26 Javascript
JavaScript indexOf方法入门实例(计算指定字符在字符串中首次出现的位置)
2014/10/17 Javascript
浅析Node.js 中 Stream API 的使用
2015/10/23 Javascript
基于Vue.js实现数字拼图游戏
2016/08/02 Javascript
form+iframe解决跨域上传文件的方法
2016/11/18 Javascript
使用get方式提交表单在地址栏里面不显示提交信息
2017/02/21 Javascript
微信小程序如何获知用户运行小程序的场景教程
2017/05/17 Javascript
微信小程序自定义底部导航带跳转功能
2018/11/27 Javascript
如何在JavaScript中正确处理变量
2020/12/25 Javascript
[31:29]完美世界DOTA2联赛PWL S3 INK ICE vs Magma 第一场 12.20
2020/12/23 DOTA
跟老齐学Python之print详解
2014/09/28 Python
使用Python脚本来控制Windows Azure的简单教程
2015/04/16 Python
在Python的Flask框架中使用日期和时间的教程
2015/04/21 Python
python生成式的send()方法(详解)
2017/05/08 Python
Python实现二叉树的最小深度的两种方法
2019/09/30 Python
TensorFlow查看输入节点和输出节点名称方式
2020/01/04 Python
pycharm 2020 1.1的安装流程
2020/09/29 Python
python 获取剪切板内容的两种方法
2020/11/28 Python
python字典与json转换的方法总结
2020/12/28 Python
HTML5实现QQ聊天气泡效果
2017/06/26 HTML / CSS
迪卡侬英国官网:Decathlon英国
2017/04/08 全球购物
Juice Beauty官网:有机美容产品,护肤与化妆品
2020/06/13 全球购物
西部世纪面试题
2014/12/05 面试题
护理学应聘自荐书范文
2014/02/05 职场文书
计算机大学生职业生涯规划书范文
2014/02/19 职场文书
上班迟到检讨书范文300字
2014/11/02 职场文书
2014年检察院个人工作总结
2014/12/09 职场文书
毕业班班主任工作总结2015
2015/07/23 职场文书
工作转正自我鉴定范文
2019/06/21 职场文书
详解CSS3浏览器兼容
2022/12/24 HTML / CSS