Laravel教程 二:路由,视图,控制器工作流程

JellyBool

JellyBool

上一篇教程我们走了那么长的路,终于把Laravel安装好了,这一篇教程我们就要进入Laravel的神奇世界了,主要是讲解Laravel的Router,Views,Controllers的工作流程,目的也就是让大家明白Laravel在处理一个get请求的时候是如何工作的。

在开始之前,我们首先得将我们的服务器启动起来,如果你使用Laravel的artisan,你可以直接:

php artisan serve

然后访问localhost:8000,就可以看到Laravel了

我这里还是使用Homestead:

homestead up

homestead 启动之后,我们就可以愉快开始写代码了。

Laravel 文件目录

然后访问我们上一节设置好的域名:blog.dev,也可以看到我们的Laravel。如果你在安装或者使用Homestead的时候遇到任何问题,都可以直接问我。

替代文字

首先,对于一个新手来接触Laravel的时候,可能你会对Laravel的文件目录感觉到很困惑,因为实在是太多东西了,到底什么是Console,Events,Providers...一大堆东西在这里。

但是不用担心,我们后续的教程会陆续讲解相关的内容。

目前我们关心的是Http/这个文件夹,你可以就简单地记忆为这个文件夹就是用来出来http请求的,比如我们在访问blog.dev的时候,Laravel是怎么将那个可爱的页面响应给我们的?这个就可以在app/Http/routes.php这个文件里面找到,就像上图显示的一样:

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

这是什么意思呢?其实这里你可以这样理解:我们注册这样一个路由,当用户发送一个get请求(简单理解就是在浏览器地址栏中访问)的时候,什么样的get请求呢?也就是什么样的浏览地址呢?恩,就是网站的根目录,也就是当一个用户访问我们站点的根目录的时候,我们应该给用户什么样的响应呢?这里我们就直接执行一个函数function () {},这个函数里面就负责加载一个视图return view('welcome');,这个试图文件位于resources/views/welcome.blade.php,这里的试图文件后缀名blade.php可能会比较疑惑,因为Laravel使用的是blade的模板引擎,如果你接触过其他的模板引擎如Twig,Smarty等,对模板引擎的理解可能会清晰一点。但是如果你在这里还是不太明白,没有关系,我后续会有专门的课程介绍blade模板。现在需要记住的是:Laravel的模板文件就是blade.php结尾的。

你可以直接打开resources/views/welcome.blade.php这个文件来看,里面其实就是一些HTML代码,easy enough。

所以上面的路由注册其实就是负责解决访问blog.dev的时候的响应。那么我们来尝试一个Hello World简单的返回:

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

回到浏览器,再次访问blog.dev,我们就会看到上面写的Hello World。

替代文字

参数

试着传入参数,我们重新注册一个路由:

Route::get('/', function () {
    return view('welcome');
});
Route::get('user/{name}', function ($name) {
    return 'Hello '.$name;
});

上面第二个就是我们自己重新注册的路由,在路由中得变量用大括号{}包裹起来,然后在处理函数中接收这个参数,访问http://blog.dev/user/guys,可以看到下面的返回结果。

上面这个时候,我们如果访问http://blog.dev/user,这是报错的,因为这个路由期望你在后面输入一个变量$name,但是你并没有,所以会报错,我们可以通过可选参数来实现这个目的

可选参数:

Route::get('user/{name?}', function ($name = null) {
    return 'Hello '.$name;
});

这个时候,再次访问http://blog.dev/user就不会报错了,但是貌似这个时候只返回了Hello,我们也可以设置一个默认值:

Route::get('user/{name?}', function ($name = 'JellyBool') {
    return 'Hello '.$name;
});

这个时候,如果我们没有输入$name这个变量,我们会返回 Hello JellyBool

替代文字

使用控制器

上面注册的这些路由是直接使用了匿名函数来返回字符串或加载视图给我们,但是我们的控制器(controller)去哪里了呢?我们怎么使用控制器呢(controllers)?首先我们需要明白,在注册路由是使用控制器在Laravel中大概是这样写的:

Route::get('/','ArticleController@index');

我们将routes.php中原来的注册路由全部删掉,只保留上面这一行代码:这行代码的意思是,当用户请求我们的网站跟目录的时候,我需要找到ArticleController并执行它的index方法,接下来,我们就需要创建我们的ArticleController了:

在命令行中执行:

php artisan make:controller ArticleController

上一篇文章说过artisan这个工具很强大,他可以用来生成我们在开发当中需要的很多东西,给我们的开发带来了很多的便利,如果你花点时间慢慢适应一下,我敢肯定,你以后会爱上Laravel的,会爱上artisan的。这里只是使用了artisanmake:controller命令,其实artisan可以干的事情很多,我们在这个教程中会一一接触到,如果你迫不及待,可以直接看官方文档:

http://laravel.com/docs/5.1/artisan

上面的命令给我们在app/Http/Controllers/目录下生成了ArticleController.php,我们打开它来看看:

替代文字

在这个文件里面,Laravel帮我们生成了一堆的方法:index()show()create()...等,然后我们刚刚在Router(routes.php文件)中注册的路由需要使用ArticleController的index方法,我们就在index()方法里面加载一个视图:

public function index()
{
    return view('articles.lists');
}

创建视图文件

这个视图文件应该是位于resources/views/articles/lists.blade.php,但是在views文件夹当中,我们并没有articles/这个文件夹和lists.blade.php,所以我们需要手动创建之。

这里需要注意的是,Laravel的view()方法会默认从views文件夹查找视图文件,所以你不用在view()方法中加入resources/views这个路径,而且你也不用将blade.php写上,Laravel会自动处理这些事情,至于views()方法articles.lists中得.就使用了路径别名,你也可以使用/来写成这样articles/lists

替代文字

创建好之后,在articles/lists.blade.php写入简单地HTML代码:

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/html">
<head>
    <meta charset="UTF-8">
    <title>Article lists page</title>
    </head>
<body>
<h1>这是文章列表页面</h1>
</body>
</html>

然后访问blog.dev/,我们就可以看到上面的模板内容了:

替代文字

到这里,不知道你对Laravel的RouterViewsControllers这三个的工作流程有没有一个清晰的认识,通常我们需要实现某个功能(或者说新创建一个页面)都是这样的:

1. 在routes.php中注册路由 ---> 2. 创建对于的控制器 ---> 3. 在控制器中得对于方法加载视图

对应得实际操作大概是这样的:

1. Route::get('/','ArticleController@index');

2. php artisan make:controller ArticleController

3. public function index()
    {
        return view('articles.lists');
    }

下一节

关于Laravel的Router,Views,Controllers的工作流程就大概讲到这里,如果你有任何疑问,可以随时在评论里面问我。然后下一节的内容会讲以下的内容:

  1. 数据库的配置和Laravel的Migration用法

  2. 将变量传给视图文件

  3. blade模板的基本用法

最后:

Happy Hacking

本文由 JellyBool 创作, 转载和引用遵循 署名-非商业性使用 2.5 中国大陆 进行许可。

共有 40 条评论

TimeIsGoOn

好东西,我当初看利用 Composer 一步一步构建自己的 PHP 框架
的时候特意把 路由的代码看了一便
"noahbuscher/macaw": "dev-master"
很有收获


建议尾部能有个 文章的跳转链接 因为我每看完一章都需要再跳回去,点其他的章节链接看
TimeIsGoOn

其实我想问

Route::get('/','ArticleController@index');

这种形式的话怎么传递参数呢?

我看有的路由定义给控制器传递参数用的是正则的写法
比如
Routers::get(‘a-(:num)-(:num)’, ‘HomeController@home’);// 比如参数 a-1-1
这种形式,然后route解析的时候使用正则把参数匹配出来,再将参数传进去
$controller->method( implode( ‘,’ , $match ) ) ;


请问laravel的router又是怎么做的呢? 还有,这样的话,岂不是要把一个项目中的所有路由全部写出来,(比如说一个项目有100多个路由,不同请求方式的) 并且都写一起也不方便阅读吧,分不清哪些路由是属于哪个功能的 有没有什么轻松的方式来进行路由的编写呢?
JellyBool

@TimeIsGoOn 首先传参数可以这样

Route::get('/{name}','ArticleController@index');

这里的参数就是name

如果你想一次写多个路由,可以使用laravel自带的机制,写成下面这个的:

Route::resource('article', 'ArticleController');

这个就会得到下面这些路由:

GET /article     index  article.index
GET /article/create create  article.create
POST    /article  store   article.store
GET /article/{article}  show    article.show
GET /article/{article}/edit edit    article.edit
PUT/PATCH   /article/{article}  update  article.update
DELETE  /article/{article}  destroy article.destroy
TimeIsGoOn
Route::resource('/demo', 'ArticleController');

查看路由

sun@sun:~/Code/blog$ php artisan route:list
+--------+----------+------------------+--------------+------------------------------------------------+------------+
| Domain | Method   | URI              | Name         | Action                                         | Middleware |
+--------+----------+------------------+--------------+------------------------------------------------+------------+
|        | GET|HEAD | demo             | demo.index   | App\Http\Controllers\ArticleController@index   |            |
|        | POST     | demo             | demo.store   | App\Http\Controllers\ArticleController@store   |            |
|        | GET|HEAD | demo/create      | demo.create  | App\Http\Controllers\ArticleController@create  |            |
|        | DELETE   | demo/{demo}      | demo.destroy | App\Http\Controllers\ArticleController@destroy |            |
|        | PATCH    | demo/{demo}      |              | App\Http\Controllers\ArticleController@update  |            |
|        | GET|HEAD | demo/{demo}      | demo.show    | App\Http\Controllers\ArticleController@show    |            |
|        | PUT      | demo/{demo}      | demo.update  | App\Http\Controllers\ArticleController@update  |            |
|        | GET|HEAD | demo/{demo}/edit | demo.edit    | App\Http\Controllers\ArticleController@edit    |            |
+--------+----------+------------------+--------------+------------------------------------------------+------------+
sun@sun:~/Code/blog$ 

这个name 是什么意思呢?
这些路由对应的 完整url请求是什么呢?

只能将控制器返回的内容输出在浏览器上,那么我想看控制器中var_dump的内容怎么看呢?比如我想看

    public function store(Request $request)
    {

    }

这里的参数是什么

JellyBool

@TimeIsGoOn

第一,name就是变量名称,比如在index($name)。然后完整地路径是domain+demo,如localhost/demo等。store(Request $request)这里的request是一个Request类的实例,可以理解为一个请求,这个请求最为整个参数传入。

TimeIsGoOn

今天遇到了一个问题,我手残把http下的controller整个文件夹都删掉了,
之后运行
make:controller
结果原来的那个 controller.php
没有重新生成,请问怎么办?

openwrtmail

@TimeIsGoOn 用artisan make只能生成一个模版文件吧。如果你做了修改估计就没有办法了~~~~

JellyBool

@TimeIsGoOn 重新手动创建一个Controller.php,写上下面的内容:

<?php

namespace App\Http\Controllers;

use Illuminate\Foundation\Bus\DispatchesJobs;
use Illuminate\Routing\Controller as BaseController;
use Illuminate\Foundation\Validation\ValidatesRequests;

abstract class Controller extends BaseController
{
    use DispatchesJobs, ValidatesRequests;
}


TimeIsGoOn

谢谢,我今天网上搜了一下,讲laravel的不管是国内国外,你这个算是版本最新的了(我在www.youtube.com上搜了视频教学,也没找到什么,很多都是讲的5.,甚至有的教程用composer下载的源都没有)
我今天看了官网的文档说明
发现还有些东西没有说 比如 Middleware ,
比如 Services 里的东西,
如果只是讲mvc怎么用的,收获比较少,
我更感兴趣的是laravel的队列 , 文件系统, 任务调度等这些服务,希望能讲一下
如果能讲讲laravel的流程就更好了,
还有。laravel和symfony是两个框架,但是laravel却能用symfony的功能包,
甚至是laravel可以使用任意的composer里的包,我也想知道,laravel是怎么做到这样的可插拔式的自由扩展的开发模式,奥秘在哪里?

JellyBool

composer是PHP的包依赖管理工具,只要是符合这个标准的,哪个框架都可以使用composer的开发包,就像nodejs的npm一样。laravel的队列和任务在我的博客其实就有用到。。。不过我实在不敢说自己能把这个只是点讲得很透。Middleware这个可以给你讲一下,后边会说到。

wedojava

@TimeIsGoOn 我的 Controller.php :

namespace App\Http\Controllers;

use Illuminate\Foundation\Bus\DispatchesJobs;
use Illuminate\Routing\Controller as BaseController;
use Illuminate\Foundation\Validation\ValidatesRequests;
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;

abstract class Controller extends BaseController
{
    use AuthorizesRequests, DispatchesJobs, ValidatesRequests;
}
JellyBool

@wedojava 哈哈哈,Good

wedojava

@JellyBool 加油,都是有梦想的人,我真是烦死了,没时间搞代码,都是得晚上才有时间,工作杂事太多了,等有孩子了估计更麻烦,只能找你们学习了。
看到你发的那个估计应该是5.1刚出来的时候的 Controller.php,我这个是升级后的,有了认证模块。

JellyBool

@wedojava 嗯,看得出你的是5.16吧?没啥烦的吧,我个人是做自己喜欢的事就好

Kirits

@JellyBool 在吗?我在你另一个网站问了些问题,有空帮我解答一下吗

JellyBool

在哪个网站?你以后有问题在这里问吧。。会经常在这里 @Kirits

JellyBool

多说一句,没事的时候花几分钟看看markdown吧,这样问问题会好一些,样式和排版好看对双方都有好处 @Kirits

Kirits

@JellyBool 好的,看过markdown了,以后会注意的了

JellyBool

OK, @Kirits

zhang3

请问jelly
Controller如何分组
我尝试了
namespace App\Http\Controllers\xxx
但是没有用.希望提示一下

JellyBool

分组?什么意思?如果说是类似admin的控制器要分开的话,可以这样的呀,在Controllers之下创建文件夹就是了,然后使用对于的namespace。 @zhang3

zhang3

@JellyBool
恩,我测试了例如Controllers下我分组成了Manage,Blog,News,等,namespace我认为也使用了正确的.但是总是抱错.提示无法找到Controllers

JellyBool

报错的话你给我看一下报错信息嘛,很大可能就是你没有正确引入Controllers。。。。。 @zhang3

zhang3

哦,鞋特!
仔细读了一遍文档,找到了问题.
thx@JellyBool

JellyBool

好的吧,解决了问题就好 @zhang3

ilaoniu

你好,为什么我按照你的方法传参, 有默认值的会报错?

AndyM129 回复 ilaoniu

原文中有介绍到:

===============
上面这个时候,我们如果访问http://blog.dev/user,这是报错的,因为这个路由期望你在后面输入一个变量$name,但是你并没有,所以会报错,我们可以通过可选参数来实现这个目的

可选参数:
Route::get(‘user/{name?}’, function (name = null) { return 'Hello '.name;
});
这个时候,再次访问http://blog.dev/user就不会报错了,但是貌似这个时候只返回了Hello,我们也可以设置一个默认值:

Route::get(‘user/{name?}’, function (name = 'JellyBool') { return 'Hello '.name;
});
这个时候,如果我们没有输入$name这个变量,我们会返回 Hello JellyBool

===============

所以依你的写法,name此时是必要参数,你只是给name了一个默认值,改为“user/{name?}”——加上一个“?”号就好了~~

sole

我在路由这块出现了点问题,

默认根目录访问没问题

但是这个

下面两个url都是报404

求指教 这是什么问题

Anonymous

点个赞 请问您这个网站是laravel开发的吗 文章中的动态图片很赞

Anonymous

恩恩,对,是使用的laravel

Anonymous

能否讲解一下laravel自带的登录控制器的登录流程?

Anonymous

请问 为什么我的artisan生成控制器里面为什么没有那些默认的方法呢

ye0205414225

老师好 想请教
我使的Laravel是目前最新版本
使用 artisan make:controller 打开档案没有预先生成的方法?

JellyBool 回复 ye0205414225

这样:

php artisan make:controller PostController --resource
ye0205414225 回复 JellyBool

小弟不才初学!
在想请教 …
若使用本地端虚拟服务器 跑路由时网址需加上public才可访问页面
则locahost:8000 不用
有什么方法能去除public吗?

JellyBool 回复 ye0205414225

若使用本地端虚拟服务器 ? 这是什么?

你指定你服务器的 root 文件就是 public 就好了

hedeqiang9436

laravel教程一打不开?没有?打开的是空白

JellyBool 回复 hedeqiang9436

你再试试。。我这边估计有点小 bug ,我修复一下

hedeqiang9436 回复 JellyBool

好了 ,辛苦了,啊哈

JellyBool 回复 hedeqiang9436

啊哈,非常感谢反馈

hedeqiang9436 回复 JellyBool

啊哈,共同进步

FuDreamer

文章上面的好多图片怎么看不了了