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基础知识:类与对象(4) 范围解析操作符(::)
Dec 13 PHP
PHP strncasecmp字符串比较的小技巧
Jan 04 PHP
Sublime里直接运行PHP配置方法
Nov 28 PHP
php实现中文字符截取防乱码方法汇总
Apr 29 PHP
PHP实现的迷你漂流瓶
Jul 29 PHP
利用PHP将部分内容用星号替换
Apr 21 PHP
Yii2实现多域名跨域同步登录退出
Feb 04 PHP
使用phpQuery获取数组的实例
Mar 13 PHP
php 一维数组的循环遍历实现代码
Apr 10 PHP
php单元测试phpunit入门实例教程
Nov 17 PHP
PHP排序算法之直接插入排序(Straight Insertion Sort)实例分析
Apr 20 PHP
PHP 7.4中使用预加载的方法详解
Jul 08 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中根据IP地址判断城市实现城市切换或跳转代码
2012/09/04 PHP
解析PHP跨站刷票的实现代码
2013/06/18 PHP
PHP7.0安装笔记整理
2015/08/28 PHP
php车辆违章查询数据示例
2016/10/14 PHP
php+javascript实现的动态显示服务器运行程序进度条功能示例
2017/08/07 PHP
如何做到打开一个页面,过几分钟自动转到另一页面
2007/04/20 Javascript
学习并汇集javascript匿名函数
2010/11/25 Javascript
javascript 获取所有id中包含某关键字的控件的实现代码
2010/11/25 Javascript
js时间戳格式化成日期格式的多种方法
2013/11/11 Javascript
JavaScript设计模式之装饰者模式介绍
2014/12/28 Javascript
JavaScript中使用自然对数ln的方法
2015/06/14 Javascript
基于Javascript实现二级联动菜单效果
2016/03/04 Javascript
js仿腾讯QQ的web登陆界面
2016/08/19 Javascript
jquery Form轻松实现文件上传
2017/05/24 jQuery
原生js封装运动框架的示例讲解
2017/10/01 Javascript
解决vuejs项目里css引用背景图片不能显示的问题
2018/09/13 Javascript
vue+Element-ui实现分页效果实例代码详解
2018/12/10 Javascript
JavaScript实现汉字转换为拼音及缩写的方法示例
2019/03/28 Javascript
微信小程序云开发如何使用云函数生成二维码
2019/05/18 Javascript
Nautil 中使用双向数据绑定的实现
2019/10/02 Javascript
nuxt+axios实现打包后动态修改请求地址的方法
2020/04/22 Javascript
jQuery 动画与停止动画效果实例详解
2020/05/19 jQuery
[04:26]2014DOTA2西雅图国际邀请赛 总决赛TOPPLAY
2014/07/22 DOTA
Python 列表(List)操作方法详解
2014/03/11 Python
python实现局域网内实时通信代码
2019/12/22 Python
解决python多线程报错:AttributeError: Can't pickle local object问题
2020/04/08 Python
python实现在线翻译
2020/06/18 Python
Python爬虫scrapy框架Cookie池(微博Cookie池)的使用
2021/01/13 Python
纯CSS3制作页面切换效果的实例代码
2019/05/30 HTML / CSS
Ralph Lauren英国官方网站:Ralph Lauren UK
2018/04/03 全球购物
十八大报告观后感
2014/01/28 职场文书
入股合作协议书
2014/10/12 职场文书
2014年绿化工作总结
2014/12/09 职场文书
长城的导游词
2015/01/30 职场文书
2015年普法依法治理工作总结
2015/05/26 职场文书
海贼王十大潜力果实,路飞仅排第十,第一可毁世界(震震果实)
2022/03/18 日漫