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之APC缓存详细介绍 apc模块安装
Jan 13 PHP
curl实现站外采集的方法和技巧
Jan 31 PHP
php读取目录所有文件信息dir示例
Mar 18 PHP
解密ThinkPHP3.1.2版本之独立分组功能应用
Jun 19 PHP
PHP 5.3新增魔术方法__invoke概述
Jul 23 PHP
php中限制ip段访问、禁止ip提交表单的代码分享
Aug 22 PHP
浅谈thinkphp5 instance 的简单实现
Jul 30 PHP
深入理解PHP的远程多会话调试
Sep 21 PHP
PHP智能识别收货地址信息实例
Jan 05 PHP
php生成微信红包数组的方法
Sep 05 PHP
laravel实现Auth认证,登录、注册后的页面回跳方法
Sep 30 PHP
基于Laravel-admin 后台的自定义页面用法详解
Sep 30 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实现汉字验证码和算式验证码的方法
2015/03/07 PHP
php程序内部post数据的方法
2015/03/31 PHP
windows下安装php的memcache模块的方法
2015/04/07 PHP
php实现网站文件批量压缩下载功能
2015/10/28 PHP
Laravel 模型使用软删除-左连接查询-表起别名示例
2019/10/24 PHP
用js实现的一个Flash滚动轮换显示图片代码生成器
2007/03/14 Javascript
js实现权限树的更新权限时的全选全消功能
2009/02/17 Javascript
js 替换功能函数,用正则表达式解决,js的全部替换
2010/12/08 Javascript
JavaScript学习笔记整理_用于模式匹配的String方法
2016/09/19 Javascript
一个简易时钟效果js实现代码
2020/03/25 Javascript
详解Vue如何支持JSX语法
2017/11/10 Javascript
Node.js创建Web、TCP服务器
2017/12/05 Javascript
详解vue渲染函数render的使用
2017/12/12 Javascript
js array数组对象操作方法汇总
2019/03/18 Javascript
Vue组件实现触底判断
2019/06/26 Javascript
利用layer实现表单完美验证的方法
2019/09/26 Javascript
node.js中 mysql 增删改查操作及async,await处理实例分析
2020/02/11 Javascript
vuex分模块后,实现获取state的值
2020/07/26 Javascript
一文秒懂JavaScript构造函数、实例、原型对象以及原型链
2020/08/25 Javascript
原生jQuery实现只显示年份下拉框
2020/12/24 jQuery
[01:29:31]VP VS VG Supermajor小组赛胜者组第二轮 BO3第一场 6.2
2018/06/03 DOTA
处理Python中的URLError异常的方法
2015/04/30 Python
python编码总结(编码类型、格式、转码)
2016/07/01 Python
关于Python如何避免循环导入问题详解
2017/09/14 Python
python数据结构之列表和元组的详解
2017/09/23 Python
python实现求解列表中元素的排列和组合问题
2018/03/15 Python
selenium3+python3环境搭建教程图解
2018/12/07 Python
Python匿名函数及应用示例
2019/04/09 Python
win10下安装Anaconda的教程(python环境+jupyter_notebook)
2019/10/23 Python
python中添加模块导入路径的方法
2021/02/03 Python
东南亚旅游平台:The Trip Guru
2018/01/01 全球购物
期终自我鉴定
2014/02/17 职场文书
优秀员工评优方案
2014/06/13 职场文书
班级学习雷锋活动总结
2014/07/04 职场文书
2014高三学生考试作弊检讨书
2014/12/14 职场文书
Python数据可视化之绘制柱状图和条形图
2021/05/25 Python