本教程示例代码见: https://github.com/johnlui/Learn-Laravel-5

在任何地方卡住,最快的办法就是去看示例代码。

本篇文章中,我将跟宝宝们一起学习 Laravel 框架最重要的部分——路由系统。

如果你读过旧的基于 Laravel 5.0 版本的此教程,你会发现那篇文章里大书特书的 Auth 系统构建已经被 Laravel 捎带手给解决了。在更早的 Laravel 4 版本的教程中,实际上我是通过让大家自己动手构建高难度的 Auth 系统来提高短期学习曲线的斜率,以便宝宝们能更快地感受到 Laravel 运行的原理。但是很遗憾,现在的 Auth 系统实在是太强大了,执行几句命令就激活了这个功能,新手其实还是云里雾里。为了弥补这个缺憾,本宝宝决定赤膊上阵,手刃路由系统,直接给大家展示 Laravel 是如何组织 MVC 架构,来控制网站运行的。

初识路由

路由系统是所有 PHP 框架的核心,路由承载的是 URL 到代码片段的映射,不同的框架所附带的路由系统是这个框架本质最真实的写照,一丝不挂,一览无余。Laravel 路由中文文档: http://laravel-china.org/docs/5.1/routing

Laravel 5 之后就把路由放到了 learnlaravel5/app/Http/routes.php 这个位置,我们先看一下目前路由中仅存的几行代码:

Route::get('/', function () {
return view('welcome');
}); Route::auth(); Route::get('/home', 'HomeController@index');

中间的一行代码 Route::auth(); 就是 Auth 系统自动注入的路由配置,我们不用深究,我们的注意力主要集中头三行和最后一行代码上。

命名空间

本宝宝一直认为 Laravel 5 除了性能大幅提升之外相对于 4 最大的进步就在于新的命名空间规划:更清晰,更合理,更有利于新手。

Laravel 4 失败的简洁

Laravel 4 时代,大量的代码都运行在根命名空间下,路由、Controller、Model 等等。看起来这么做可以少写几行枯燥的 use xxxx; ,实则是对于命名空间的误使用,而且对于新手学习命名空间是有毒的。

绝对类名

Laravel 5 全面引入了 psr-4 命名空间标准:命名空间和实际文件所在的文件夹层级一致,文件夹首字母大写即为此文件的约定命名空间。举个小栗子:learnlaravel5/app/Http/Controllers/HomeController.php 的绝对类名为:\App\Http\Controllers\HomeController , learnlaravel5/app/User.php的绝对类名为: \App\User 。

“绝对类名”是本宝宝自创的:在启用了命名空间的系统中,子命名空间下的类有一个全局都可以直接访问的名称,这个名称就是该类的命名空间全称。虽然命名空间在“实用主义”的 PHP 语言里看起来十分古怪,不过他也还是 PHP 嘛,依然遵循 PHP 的运行原理和哲学。同理,Laravel 无论多么强大,他都是 PHP 代码写成的,所以当你苦于 Laravel 没有提供某个你需要的功能时,不要惊慌不要着急,just write the code in the PHP way。

psr-4 的官方英文文档在这里: http://www.php-fig.org/psr/psr-4/

好用的资料

命名空间其实没什么特别难的地方,我曾经写过一篇文章专门扒光命名空间的秘密:

《PHP 命名空间 解惑

基础路由解析

闭包路由

路由文件中前三行即为闭包路由:

Route::get('/', function () {
return view('welcome');
});

闭包路由使用闭包作为此条请求的响应代码,方便灵活,很多简单操作直接在闭包里解决即可。例如“输出服务器当前时间”:

Route::get('now', function () {
return date("Y-m-d H:i:s");
});

如果你想得到北京时间,请在 learnlaravel5/config/app.php 第 55 行左右把 timezone 设置为上海:

'timezone' => 'Asia/Shanghai',

这时候访问 http://fuck.io:1024/now 可以得到如下结果:

控制器@方法 路由

闭包路由虽然灵活强大,不过大多数场景下我们还是需要回归到 MVC 架构的:

Route::get('/home', 'HomeController@index');

这行路由代码的意思想必大家都能猜到一二了:当以 GET 方法访问http://fuck.io:1024/home 的时候,调用 HomeController 控制器中的 index 方法(函数)。同理,你可以使用 Route::post('/home', 'HomeController@indexPost'); 响应 POST 方法的请求。

控制器@方法 调用原理浅析

Laravel 的路由跟所有 PHP 框架的路由一样,都是用的最简单直接的 PHP 方式来调用控制器中的方法的:使用字符串初始化类得到对象,调用对象的指定方法,返回结果。下面我简单罗列几步对 Laravel 路由调用过程的探测,感兴趣的话可以自己研究。

learnlaravel5/app/Providers/RouteServiceProvider.php

全局搜索 routes.php ,我们找到了这个文件。此文件最后的 mapWebRoutes 方法,给所有的路由同意加进了一个路由组,定义了一个命名空间和一个中间件:

protected function mapWebRoutes(Router $router)
{
$router->group([
'namespace' => $this->namespace, 'middleware' => 'web',
], function ($router) {
require app_path('Http/routes.php');
});
}

顺着这个函数往上看,你会发现命名空间定义的地方:

protected $namespace = 'App\Http\Controllers';

之后命名空间、类、方法是如何传递的呢?

learnlaravel5/vendor/laravel/framework/src/Illuminate/Routing/ControllerDispatcher.php

经过简单的追踪,我们找到了这个文件。让我们在 dispatch 方法中增加一行var_dump($controller); ,刷新就可以看到页面上如下的输出:

这就是我们要调用的控制器类的“绝对类名”。

最后一步

Laravel 使用了完整的面向对象程序架构,对控制器的调用进行了超多层封装,所以最简单地探测方式其实是手动抛出错误,这样就可以看到完整的调用栈:

在 HomeController 的 index 方法里的 return 之前增加一行 throw new \Exception("我故意的", 1); ,刷新页面,你将看到以下画面:

我们可以看到,是learnlaravel5/vendor/laravel/framework/src/Illuminate/Routing/Controller.php 第 80 行最终驱动起了 HomeController:

public function callAction($method, $parameters)
{
return call_user_func_array([$this, $method], $parameters);
}

具体的细节不再详解,宝宝如果感兴趣的话,把这些方法一个一个地都看一遍吧,相信对于你理解 Laravel 运行原理很有帮助。其实 PHP 跟字符串结合的紧密程度已经紧逼 js 和 JSON 了。结尾分享一个小彩蛋: 这个laravel路由怎么写?

2016 版 Laravel 系列入门教程(二)【最适合中国人的 Laravel 教程】的更多相关文章

  1. 2016 版 Laravel 系列入门教程

    2016 版 Laravel 系列入门教程 (1) - (5) http://www.golaravel.com/post/2016-ban-laravel-xi-lie-ru-men-jiao-ch ...

  2. Laravel 5 系列入门教程(一)【最适合中国人的 Laravel 教程】

    Laravel 5 系列入门教程(一)[最适合中国人的 Laravel 教程] 分享⋅ johnlui⋅ 于 2年前 ⋅ 最后回复由 skys215于 11个月前 ⋅ 17543 阅读   原文发表在 ...

  3. 一步步实现windows版ijkplayer系列文章之二——Ijkplayer播放器源码分析之音视频输出——视频篇

    一步步实现windows版ijkplayer系列文章之一--Windows10平台编译ffmpeg 4.0.2,生成ffplay 一步步实现windows版ijkplayer系列文章之二--Ijkpl ...

  4. Laravel 系列入门教程(三)【最适合中国人的 Laravel 教程】

    在本篇文章中,我们将尝试构建一个带后台的简单博客系统.我们将会使用到 路由.MVC.Eloquent ORM 和 blade 视图系统. 简单博客系统规划 我们在教程一中已经新建了一个继承自 Eloq ...

  5. 2016 版 Laravel 系列入门教程(五)【最适合中国人的 Laravel 教程】

    本教程示例代码见: https://github.com/johnlui/Learn-Laravel-5 在任何地方卡住,最快的办法就是去看示例代码. 本文是本系列教程的完结篇,我们将一起给 Arti ...

  6. 2016 版 Laravel 系列入门教程(三)【最适合中国人的 Laravel 教程】

    本教程示例代码见: https://github.com/johnlui/Learn-Laravel-5 在任何地方卡住,最快的办法就是去看示例代码. 在本篇文章中,我们将尝试构建一个带后台的简单博客 ...

  7. 2016 版 Laravel 系列入门教程(一)【最适合中国人的 Laravel 教程】

    本教程示例代码见: https://github.com/johnlui/Learn-Laravel-5 在任何地方卡住,最快的办法就是去看示例代码. 本文基于 Laravel 5.2 版本,无奈 5 ...

  8. 2016 版 Laravel 系列入门教程(四)【最适合中国人的 Laravel 教程】

    本教程示例代码见: https://github.com/johnlui/Learn-Laravel-5 在任何地方卡住,最快的办法就是去看示例代码. 本篇文章中,我将跟大家一起实现 Article ...

  9. Laravel 系列入门教程(二)【最适合中国人的 Laravel 教程】

    本篇文章中,我将跟大家一起体验 Laravel 框架最重要的部分——路由系统. 如果你读过 2015 版的教程,你会发现那篇文章里大书特书的 Auth 系统构建已经被 Laravel 捎带手给解决了. ...

随机推荐

  1. Error querying database. Cause: java.lang.IllegalArgumentException: Mapped Statements collection does not contain value for …

    编译通过并且运行web成功后,访问的页面不需要连接数据库,不牵扯到反射调用实体类就不会报错, 报错内容如下: [WARNING] org.springframework.web.util.Nested ...

  2. Android Studio调试功能使用总结【转】

    Android Studio调试功能使用总结[转]   这段时间一直在使用Intellij IDEA, 今天把调试区工具的使用方法记录于此. 先编译好要调试的程序. 1.设置断点 选定要设置断点的代码 ...

  3. redis unwatch discard

    UNWATCH UNWATCH 取消 WATCH 命令对所有 key 的监视. 如果在执行 WATCH 命令之后, EXEC 命令或 DISCARD 命令先被执行了的话,那么就不需要再执行UNWATC ...

  4. [转]ActionScript 3.0入门:Hello World、文件读写、数据存储(SharedObject)、与JS互调

    本文转自:http://www.cnblogs.com/artwl/p/3396330.html 近期项目中可能要用到Flash存取数据,并与JS互调,所以就看了一下ActionScript 3.0, ...

  5. NOIP2010普及组T3 接水问题 ——S.B.S.

    题目描述 学校里有一个水房,水房里一共装有 m 个龙头可供同学们打开水,每个龙头每秒钟的 供水量相等,均为 1. 现在有 n 名同学准备接水,他们的初始接水顺序已经确定.将这些同学按接水顺序从 1到 ...

  6. uva 839 Not so Mobile-S.B.S.

    Before being an ubiquous communications gadget, a mobilewas just a structure made of strings and wir ...

  7. Listview的点击事件

    上篇文章总结了如何自定义listview的显示内容,然而listview不能只是提供显示功能,还必须能够点击它显示一些东西: listView.setOnItemClickListener(new O ...

  8. 匈牙利算法 cojs.tk 搭配飞行员

    cojs.tk  搭配飞行员 ★★☆   输入文件:flyer.in   输出文件:flyer.out   简单对比时间限制:1 s   内存限制:128 MB [问题描述]     飞行大队有若干个 ...

  9. Unity-WIKI 之 DebugLine

    脚本功能 在Unity中要使用画线功能,需要添加LineRenderer 组件,或打开Gizmos功能,下面这个组件为开发带来了方便 功能预览 搭建步骤 1.创建“Plugins” 文件夹 2.在“P ...

  10. Unity脚本生命周期

    前言 说到生命周期,影响最深刻的是,在接触Java的JSF组件时,JSF组件的五大生命周期,全要默写出来,嘿嘿…… 总结这两天在写小怪和掉落的糖葫芦时,老是遇到GameObject未销毁,一直存在场景 ...