最适合入门的 Laravel 入门教程 (五)

路由咱会创建了;
控制器也有了;
接下来要搞的就是把两者关联起来了;
最适合入门的laravel初级教程(三)
我们讲过 Route 的 get 或者 post 方法第一个参数就是我们要定义的路由;
就是我们在地址栏请求的那段url;
第二个参数可以是一个闭包函数;
里面写请求定义的路由时执行的内容;
上篇文章我们说过;
如果把代码都放这个闭包函数中是臃肿且难以维护的;
所以就需要使用控制器了;
很显然;控制器就是来替代这第二个参数的闭包函数的;
写起来也非常简单直接写控制器名即可;
然后用 @ 符号分割控制器和控制器的方法

Route::get('article/index', 'ArticleController@index');
Route::get('article/create', 'ArticleController@create');
Route::post('article/store', 'ArticleController@store');


可以在控制器中写点内容;

访问定义的路由就可以看到内容了;

一切都是这么的完美;
但是如果你和我一样帅;
额;不是;
如果你和我一样懒且善于总结思考;
你会发现这三条路由都是以 article/ 为前缀的;
在路由中我们应该怎么减少这种重复呢?
这就是我们接着要讲的分组的概念;
路由组就是把一些有相同特性的路由放在一个组里面;
我们先来定义一个前缀路由组;
上面这3条路由就可以改造成这个样子了;

Route::prefix('article')->group(function () {
    Route::get('index', 'ArticleController@index');
    Route::get('create', 'ArticleController@create');
    Route::post('store', 'ArticleController@store');
});

随着项目的扩大;
如果控制器都直接放在 app/Http/Controllers 目录下的话;
那维护起来也开始略头疼了;
于是就可以为控制器分目录存放了;
比如说我要建一个 app/Http/Controllers/Admin/ArticleController.php;
再建一个 app/Http/Controllers/Home/ArticleController.php ;
命令行也是可以加目录的;

php artisan make:controller Admin/ArticleController --resource
php artisan make:controller Home/ArticleController --resource

再在新建的控制器中写点内容加以区分;

这种多级目录是不需要指明目录的;
只需要指明相对于app/Http/Controllers 目录的 namespace 即可;

Route::prefix('admin/article')->namespace('Admin')->group(function () {
    Route::get('index', 'ArticleController@index');
    Route::get('create', 'ArticleController@create');
    Route::post('store', 'ArticleController@store');
});

group 是可以嵌套的;
那么上面这样的路由还可以改造下;

Route::prefix('home')->namespace('Home')->group(function () {
    Route::prefix('article')->group(function () {
        Route::get('index', 'ArticleController@index');
        Route::get('create', 'ArticleController@create');
        Route::post('store', 'ArticleController@store');
    });
});

访问起来就是这样的了;

因为 Admin 目录下我们还会创建更多的路由器;
所以;我们应该使用 group 嵌套的这种方式;
比如说我们再有一个 app/Http/Controllers/Home/TagController.php;
那路由就是这样的了;

Route::prefix('home')->namespace('Home')->group(function () {
    Route::prefix('article')->group(function () {
        Route::get('index', 'ArticleController@index');
        Route::get('create', 'ArticleController@create');
        Route::post('store', 'ArticleController@store');
    });
    Route::prefix('tag')->group(function () {
        Route::get('index', 'TagController@index');
        Route::get('create', 'TagController@create');
        Route::post('store', 'TagController@store');
    });
});

除了文档上讲的这种方式;
其实以前版本的 laravel 还有另一种定义路由组的方式;

Route::group(['prefix'=>'admin', 'namespace'=>'Admin'], function () {
    Route::group(['prefix'=>'article'], function () {
        Route::get('index', 'ArticleController@index');
        Route::get('create', 'ArticleController@create');
        Route::post('store', 'ArticleController@store');
    });
});

就是把 prefix 和 namespace 这些都作为 group 方法的第一个参数;
不过现在不推荐这种写法了;
不过因为很多以前的项目都是这样写的;
这里讲一下让童鞋们查看别人以前的项目的时候能理解而不迷茫;

到这里我们已经学会了如何组织多级目录了;
为了讲解的简单;
我们回到 app/Http/Controllers/ArticleController.php 文件接着往下看;
会发现命令行创建的控制器里面有个 edit 方法;

public function edit($id)
{
    //
}

edit 方法有个 $id 参数;
这个参数是干什么用的呢?
通过名字我们很容易就明白这是用来修改数据的;
id 一般又是数据库的自增字段;
那这就是要修改指定 id 的数据了;
但是这个 id 是哪传来的呢?
下面就到了讲解路由参数的时候了;
定义路由的时候我们是可以定义路由参数的;
我们接着上面的路由加一个 edit 的;

Route::prefix('article')->group(function () {
    Route::get('index', 'ArticleController@index');
    Route::get('create', 'ArticleController@create');
    Route::post('store', 'ArticleController@store');
    Route::get('edit/{id}', 'ArticleController@edit');
});

我们在定义路由的时候用花括号包一个变量名;
那这个变量就可以直接传到控制器方法中;
然后在地址栏传什么控制器中就可以接到什么;
为了方便测试我们在这个方法中返回 id ;

public function edit($id)
{
    return '地址栏传的参数是:'.$id;
}

携带着路由参数通过路由访问这个方法;

这里面有个容易栽跟头的地方;
就是控制器中的参数名跟路由参数名不是必须相同的;
也就是说我这样写也是可以的;

public function edit($a)
{
    return '地址栏传的参数是:'.$a;
}

一个路由参数的时候这倒不会觉得什么;
一旦定义多个路由参数的时候;
这个坑就真的坑了;

Route::prefix('article')->group(function () {
    // ...
    Route::get('edit/{id}/{name}', 'ArticleController@edit');
});

在控制器中获取路由参数的时候;

public function edit($name, $id)
{
    return 'id是:' . $id . '<br>name是:' . $name;
}

访问 http://bjyblog.test/article/edit/666a/白俊遥
在你以为闭着眼都知道结果的时候;
一只硕大的幺蛾子飞了过来;

你发现 id 和 name 没对上;
该敲黑板画重点了筒子们;
路由参数中的第一个参数对应控制器中的第一个路由参数;
以此类推;
在控制器中路由参数跟参数名是没关系的;
只跟顺序有关;

再个 id 一般都是纯数字;
这里却传了字母 ;
我们应该怎么约束下 id 呢?
laravel 方方面面都为我们考虑到了;
我们加个 where 就行了;

Route::prefix('article')->group(function () {
    // ...
    Route::get('edit/{id}/{name}', 'ArticleController@edit')->where('id', '[0-9]+');
});

这样就只能传数字了;
其实大多的表都是用 id 做主键的;
如果每个路由都手动定义一遍约束;
那也是挺麻烦的;
laravel 又一次方方面面都为我们考虑到了;
找到 app/Providers/RouteServiceProvider.php 这个文件;
在 boot 方法中可以定义全局约束;

public function boot()
{
    Route::pattern('id', '[0-9]+');

    parent::boot();
}

这样就不需要为每条带 id 参数的路由定义约束了;
以后所有带 id 参数的路由就只能传数字了;
不懂这个 RouteServiceProvider 的话没关系不要纠结在这;
就先当是固定用法;
以后慢慢懂;

跟路由参数容易搞混的是请求参数;
路由参数?请求参数?傻傻分不清楚;
举个栗子;

Route::prefix('article')->group(function () {
    // ...
    Route::get('edit/{id}/{name}', 'ArticleController@edit');
});

bjyblog.test/article/edit/666/白俊遥?music=越过山丘&book=平凡世界
id 和 name 就是路由参数;
music 和 book 就是请求参数;
路由参数的获取我们已经会了;
那请求参数怎么获取呢?
我们再回控制器中转悠转悠还会发现 update 方法;

public function update(Request $request, $id)
{
    //
}

这个 Request $request 就是我们用来获取请求参数的关键;
它的意思是向控制器的方法传一个 $request 它是一个 Request 类;
我们可以把我们的 edit 方法也加个 $request ;

    public function edit(Request $request, $id, $name)
    {
        $music = $request->input('music');
        $book = request()->input('book');
        $str = <<<php
id: $id <br>
name: $name <br>
music: $music <br>
book: $book <br>
php;
        return $str;
    }

这个 Request $request 是不会影响路由参数的顺序的;
它放前放后都是可以的;
我们访问这个方法并携带请求参数;

Request 类有一个 input 方法;
把要获取的参数名传给它就可以了;
我上面示例中还用了个 request() 函数;
它跟 Request $request 效果是一样的;
$request 可以方便复用;
所以在控制器中更推荐使用 $request ;
如果传的请求参数比较多的时候;
这样一个一个的获取还是麻烦;
Request 还有个 all 方法就可以获取全部的请求参数;

    public function edit(Request $request, $id, $name)
    {
        dump($request->all());
    }

dump 是 laravel 自带的一个打印函数;
就是 php 自带的 var_dump 函数的升级版;
打印出来的效果是这样的;

如果想打印数据并 die 掉可以使用 dd() 函数;
如果只想从一大堆请求参数中获取指定的请求参数
Request 还有个 only 方法;

    public function edit(Request $request, $id, $name)
    {
        dump($request->only('music', 'book'));
    }

那如果想排除某个参数剩下的全要呢?
Request 还有个 except 方法;

    public function edit(Request $request, $id, $name)
    {
        dump($request->except('music'));
    }

再次赞美 laravel 的体贴周到;

本文为白俊遥原创文章,转载无需和我联系,但请注明来自白俊遥博客 https://baijunyao.com

本作品采用《CC 协议》,转载必须注明作者和本文链接
《L04 微信小程序从零到发布》
从小程序个人账户申请开始,带你一步步进行开发一个微信小程序,直到提交微信控制台上线发布。
《L02 从零构建论坛系统》
以构建论坛项目 LaraBBS 为线索,展开对 Laravel 框架的全面学习。应用程序架构思路贴近 Laravel 框架的设计哲学。
讨论数量: 3
$music = $request->input('music');
        $book = request()->input('book');//? $book = $request->input('book');
        $str = <<<php
id: $id <br>
name: $name <br>
music: $music <br>
book: $book <br>
php;
        return $str;
6年前 评论

写得确实棒

4年前 评论

写的跟好啊,怎么不更了呀

4年前 评论

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!