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实现网站插件机制的方法
Nov 10 PHP
使用PHP实现密保卡功能实现代码<打包下载直接运行>
Oct 09 PHP
深入PHP5中的魔术方法详解
Jun 17 PHP
windows下配置apache+php+mysql时出现问题的处理方法
Jun 20 PHP
CodeIgniter使用smtp服务发送html邮件的方法
Jun 10 PHP
详解PHP错误日志的获取方法
Jul 20 PHP
PHP Callable强制指定回调类型的方法
Aug 30 PHP
PHP简单实现模拟登陆功能示例
Sep 15 PHP
Laravel框架使用Redis的方法详解
May 30 PHP
Laravel框架查询构造器 CURD操作示例
Sep 04 PHP
php解决安全问题的方法实例
Sep 19 PHP
Laravel框架使用技巧之使用url()全局函数返回前一个页面的地址方法详解
Apr 06 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下打开URL地址的几种方法小结
2010/05/16 PHP
PHP5中实现多态的两种方法实例分享
2014/04/21 PHP
php中数据库连接方式pdo和mysqli对比分析
2015/02/25 PHP
javascript面向对象之二 命名空间
2011/02/08 Javascript
js随机颜色代码的多种实现方式
2013/04/23 Javascript
js控制表单奇偶行样式的简单方法
2013/07/31 Javascript
js简单实现HTML标签Select联动带跳转
2013/10/23 Javascript
js数组与字符串的相互转换方法
2014/07/09 Javascript
jquery中使用循环下拉菜单示例代码
2014/09/24 Javascript
js运动动画的八个知识点
2015/03/12 Javascript
js实现漂浮回顶部按钮实例
2015/05/06 Javascript
JS创建对象几种不同方法详解
2016/03/01 Javascript
浅谈js for循环输出i为同一值的问题
2017/03/01 Javascript
Vue-router 类似Vuex实现组件化开发的示例
2017/09/15 Javascript
微信小程序表单弹窗实例
2018/07/19 Javascript
JS实现textarea通过换行或者回车把多行数字分割成数组并且去掉数组中空的值
2018/10/29 Javascript
微信小程序 如何保持登录状态
2019/08/16 Javascript
vue h5移动端禁止缩放代码
2019/10/28 Javascript
微信小程序实现点击导航条切换页面
2020/11/19 Javascript
[03:32]2014DOTA2西雅图邀请赛 CIS外卡赛赛前black专访
2014/07/09 DOTA
python在命令行下使用google翻译(带语音)
2014/01/16 Python
python使用multiprocessing模块实现带回调函数的异步调用方法
2015/04/18 Python
Python File readlines() 使用方法
2018/03/19 Python
Django 通过JS实现ajax过程详解
2019/07/30 Python
CSS3 选择器 基本选择器介绍
2012/01/21 HTML / CSS
css3编写浏览器背景渐变背景色的方法
2018/03/05 HTML / CSS
波兰品牌内衣及泳装网上商店:Astratex.pl
2017/02/03 全球购物
区优秀教师事迹材料
2014/02/10 职场文书
化妆品店促销方案
2014/02/24 职场文书
会计岗位职责模板
2014/03/12 职场文书
幼儿园小班评语大全
2014/04/17 职场文书
美食节目策划方案
2014/05/31 职场文书
国际贸易实训报告
2014/11/05 职场文书
抗洪救灾感谢信
2015/01/22 职场文书
你真的了解redis为什么要提供pipeline功能
2021/06/22 Redis
Python内置数据结构列表与元组示例详解
2021/08/04 Python