琯琯博客 纸上得来终觉浅,绝知此事要躬行。

Laravel 系列教程(五)控制器

琯琯
2018-01-13

最近有事耽搁了一段时间;

以至于让这篇文章迟到了一段时间;

上上篇文章我就简单的聊了下目录;

下面就有请控制器上场了;

在使用thinkphp创建控制器的时候;

我们都是手动创建一个php文件;

然后再手动写控制器名继承;

这种重复劳动对我这懒人来说是相当折磨的;

so; 为了偷懒;

我当年还专门研究怎么使用编辑器快速生成代码;

使用 sublime 的童鞋们可以瞅两眼这个项目;

为 sublime 编写的 thinkphp 代码块 我当年一度觉得;

我这个项目可以让男人用了沉默;

女人看了流泪;

真是大大的提高了编码的效率;

一直也没抽出时间写篇文章好好讲;

有兴趣的看看图根据 readme 研究吧;

然而当我遇到了laravel;

我发现我真的是弱爆了;

laravel 才是真正懂开发者的需求;

并且提供了靠谱的解决方案;

laravel创建控制器是使用命令行的;

比如说我要创建个 IndexControler 控制器;

php artisan  make:controller IndexController

在命令敲上这行命令;

就会创建 app/Http/Controllers/IndexController.php 文件;

命名空间啥的都不需要自己考虑;

连继承都自动 extends 了;

laravel的控制器是不需要.class.php后缀的直接 控制器名.php即可;

目录结构我上篇文章简单的讲了下;

app
├─Http 请求处理目录
│  ├─Controller  控制器目录
│  │  ├─admin  后台Admin模块
│  │  │  ├─IndexController.php 后台首页控制器
│  │  │  ├─CategoryController.php 分类管理控制器
│  │  ├─home   前台Home模块
│  │  │  ├─IndexController.php 前台首页控制器
│  │  │  ├─ArticleController.php 文章展示控制器
│  │  ├─user   用户User模块
│  │  │  ├─IndexController.php 用户首页控制器
│  │  │  ├─TagController.php 标签管理控制器

默认情况下;

artisan 生成的控制器全部是在 app/Http/Controllers 下的;

但是如果项目慢慢变的庞大后就会显得比较凌乱了;

而且;

而且给控制器命名都能成为一件纠结的事;

比如说我前台后台都有对文章的管理;

那这两个 ArticleController 分别怎么怎么命名?

在各种权衡利弊后;

我是推荐如我上面这种按照模块进行划分的;

使用命令行创建控制器的话直接加上目录即可;

php artisan  make:controller Home/IndexController

就会创建 app/Http/Controllers/Home/IndexController.php 文件;

在 thinkphp 中;

如果我们想对一些控制器制定比较宽泛的访问权限;

比如说让 user 模块下的控制器;

必须登录才可访问;

比较常见的做法是通过继承解决;

先创建 UserBaseController 基础控制器;

在 UserBaseController 的 __contruct 方法中判断必须登录才可访问;

然后让 user 模块下的控制器都继承 UserBaseController ;

但是通过继承 BaseController 的方案解决的非常之不细致;

如果只想让控制器中的某几个方法必须登录才可访问;

处理起来就比较麻烦了;

在 laravel 中;

则是使用了中间件的模式;

HTTP 中间件 中间件更加解耦; 调用方便 职责也更加专一;

对比着tp来理解的话;

可以简单的把中间件比作是 **BaseController 中 __construct;

所有的请求都要先通过定义的中间件;

过了__construct ;

咱获取请求数据;

假设咱要向 home/index/index 中以GET方式传递id=1、name=白俊遥 的数据;

thinkphp 的 url可以是这样的;

1:https://baijunyao.com/home/index/index?id=1&name=白俊遥

当然有更美观点的 pathinfo 模式;

2:https://baijunyao.com/home/index/index/id/1/name/白俊遥; 或者搞的更花哨但不实用点的;

3:https://baijunyao.com/home/index/index/id/1?name=白俊遥; 但是不管怎么变控制器中获取参数的方式都如下:

namespace Home\Controller;
use Common\Controller\HomeBaseController;
class IndexController extends HomeBaseController {
    public function index(){
        // 原生php获取方式
        echo $_GET['id']; // 输出 1
        echo $_GET['name']; // 输出 白俊遥
        // 框架封装的更安全的I函数方式
        echo I('get.id'); // 输出1
        echo I('get.name'); // 输出 白俊遥
    }
}

但是上面三种在 laravel 中的意义是不同的;

相比于 thinkphp laravel 中除了请求参数还有个路由参数的概念;

第1种比较简单了和 thinkphp 一样这就是单纯的get传2个参数;

按照三级目录模式先定义路由;

routes/web.php

// Home模块下 三级模式
Route::group(['namespace' => 'Home', 'prefix' => 'home'], function () {
    Route::group(['prefix' => 'index'], function () {
        Route::get('index', 'IndexController@index');
    });
});

控制器中如下;

app/Http/Controllers/Home/IndexController.php

<?php
namespace App\Http\Controllers\Home;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
class IndexController extends Controller
{
    public function index(Request $request)
    {
        echo $request->input('id'); // 输出 1
        echo $request->input('name'); // 输出 白俊遥
    }
}

第2种在 laravel 没有这样用的直接忽略好了;

重点说下第3种; 但是需要稍加改造;

id可以不要了 https://baijunyao.com/home/index/index/1?name=白俊遥; laravel 中有一个路由参数的概念;

针对上面这个链接就是指的高亮的的1 https://baijunyao.com/home/index/index/1?name=白俊遥 name 则是请求参数;

id可以不放在url的参数中了; 而是定义在路由中

// Home模块下 三级模式
Route::group(['namespace' => 'Home', 'prefix' => 'home'], function () {
    Route::group(['prefix' => 'index'], function () {
        Route::get('index/{id}', 'IndexController@index');
    });
});

id和name获取方式也不一样了;

<?php
namespace App\Http\Controllers\Home;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
class IndexController extends Controller
{
    public function index($id, Request $request)
    {
        echo $id; // 输出 1
        echo $request->input('name'); // 输出 白俊遥
    }
}

接着本来是要从数据库获取数据了;

这个放在下篇文章讲解模型的时候细说;

直接对比着分配数据和引入前端页面;

thinkphp中的分配数据是使用 assign;

以文章首页的方法为例;

public function index(){
    $assign = [
        'title' => '白俊遥文章的标题',
        'content' => '白俊遥文章的内容'
    ]
    $this->assign($assign);
    $this->display('Home/Index/index');
}

如果当前的方法要引入的html页面跟控制器目录结构一致;

那 display 是可以不传参数的;

Home 模块下的 IndexController 的 index 方法中;

display 不传参数跟传'Home/Index/index'是一样的;

$this->display()
$this->display('Home/Index/index');

到了 laravel 中就是这个样子的了;

public function index(){
    $assign = [
        'title' => '白俊遥文章的标题',
        'content' => '白俊遥文章的内容'
    ]
    return view('home.index.index', $assign);
}

laravel 用 view 函数可以实现分配和引入页面两个功能;

第一个参数是要引入的页面相对于resources/view的路径;

如果习惯 thinkphp 的用斜线分割的方式;

laravel 也是支持的; 下面这两种写法是相等的;

return view('home.index.index', $assign);
return view('home/index/index', $assign);

这里推荐使用点 . 分割;

因为 phpstorm 默认是可以识别laravel项目的.分割的;

在控制器中按着 ctrl 点 'home.index.index' 是可以直接打开该文件的;

相当之方便;

还有需要特别注意的地方是return; 控制器中的方法返回页面或者redirect都必须要 return ;

原文链接


评论

内容导航