中级任务清单 | 教程 |《Laravel 5.1 中文文档 5.1》| Laravel China 社区


本站和网页 https://learnku.com/docs/laravel/5.1/quickstart-intermediate/1049 的作者无关,不对其内容负责。快照谨为网络故障时之索引,不代表被搜索网站的即时页面。

中级任务清单 | 教程 |《Laravel 5.1 中文文档 5.1》| Laravel China 社区
Laravel
话题列表
社区 Wiki
优质外文
招聘求职
Laravel 实战教程
社区文档
登录
注册
Laravel 5.1 中文文档
展开或关闭
前言
翻译说明
发行说明
升级导引
贡献导引
环境配置
安装
Homestead
基本功能
路由
中间件
控制器
请求
响应
视图
Blade 模板
教程
初级任务清单
中级任务清单
系统架构
请求生命周期
应用程序结构
服务提供者
服务容器
Contracts
Facades
系统服务
用户认证
用户授权
Artisan 命令行
交易
缓存
集合
Elixir
加密与解密
错误与日志
事件
文件系统与云存储
哈希
辅助函数
本地化
邮件
扩展包开发
分页
队列
Redis
Session
Envoy
任务调度
测试
表单验证
数据库
入门
查询构造器
数据库迁移
数据填充
Eloquent ORM
入门
模型关联
Eloquent 集合
Getter/Setter
序列化
Laravel
首页
Laravel
Go
PHP
Vue.js
Python
Java
MySQL
Rust
LK
Elasticsearch
F2E 前端
Server
程序员
Database
DevTools
Computer Science
手机开发
AdonisJS
社区
Wiki
教程
Laravel 实战教程首页
《L01 Laravel 教程 - Web 开发实战入门》
《L02 Laravel 教程 - Web 开发实战进阶》
《L03 Laravel 教程 - 实战构架 API 服务器》
《L04 Laravel 教程 - 微信小程序从零到发布》
《L05 Laravel 教程 - 电商实战》
《L06 Laravel 教程 - 电商进阶》
《LX1 Laravel / PHP 扩展包视频教程》
《LX2 PHP 扩展包实战教程 - 从入门到发布》
《L07 Laravel 教程 - Laravel TDD 测试实战》
《LX3 Laravel 性能优化入门》
《LX4 Laravel / PHP 五分钟视频》
文档
社区文档首页
《Laravel 中文文档》
《Laravel 速查表》
《PHP 代码简洁之道》
《Laravel 编码技巧》
《Dcat Admin 中文文档》
《Laravel Nova 中文文档》
《Lumen 中文文档》
《Dingo API 中文文档》
《 Laravel 项目开发规范》
《构建 Laravel 开发环境》
登录
注册
微信登录
提交改进
中级任务清单
5.1
9.x
8.5
8.x
7.x
6.x
5.8
5.7
5.6
5.5
5.4
5.3
5.2
5.1
Laravel 5.1 中文文档
未匹配的标注
本文档最新版为 9.x,旧版本可能放弃维护,推荐阅读最新版!
中级任务清单
简介
安装
准备数据库
数据库迁移
Eloquent 模型
Eloquent 关联
路由
显示视图
认证
任务控制器
构建布局与视图
定义布局
定义子视图
增加任务
验证
创建任务
显示已有的任务
依赖注入
显示任务
删除任务
增加删除按钮
路由模型绑定
授权
删除该任务
简介
此快速入门指南为 Laravel 框架提供了高级的介绍,其中内容包括
数据库迁移
Eloquent ORM
路由
认证
授权
依赖注入
验证
视图
Blade 模版。
如果你已经有 Laravel 框架或 PHP 的基础,那么这会是个很好的开头。
我们会构建一个简单的任务清单,可以使用它追踪所有想完成的任务(典型的「代办事项清单」例子)。与「基本」快速入门教程不同,此教程会允许用户在应用程序创建帐号并认证。此项目完整的源代码 在 GitHub 上。
安装
首先你需要安装一个全新的 Laravel 框架。你可以选择使用 Homestead 虚拟机 或是其它本机 PHP 环境来运行框架。只要你准备好了本机环境,就可以使用 Composer 安装 Laravel 框架:
composer create-project laravel/laravel quickstart --prefer-dist
你可以随意阅读快速入门指南的剩余部分;不过,如果你想下载这个快速入门指南的源代码并在你的本机机器运行,那么你需要克隆它的 Git 代码仓库并安装依赖:
git clone https://github.com/laravel/quickstart-intermediate quickstart
cd quickstart
composer install
php artisan migrate
欲了解更多关于构建本机 Laravel 开发环境的文档,请查阅完整的 Homestead 及 安装 文档。
准备数据库
数据库迁移
首先,让我们使用迁移来定义数据表以容纳我们所有的任务。Laravel 的数据库迁移提供了一个简单的方式,使用流畅、一目了然的 PHP 代码来定义数据表的结构与修改。
你无需再告诉团队成员要手动增加字段至他们本机的数据库中,他们只需要运行你提交到版本控制的迁移,即可应用数据库修改。
users 数据表
因为我们要让用户可以在应用程序中创建他们的帐号,所以我们需要一张数据表来保存我们的用户。值得庆幸的是,Laravel 已经附带了创建 users 数据表的迁移,所以我们没必要再手动生成一个。默认的 users 数据表迁移位于 database/migrations 目录中。
tasks 数据表
下一步,让我们构建一张将容纳所有任务的数据表。Artisan 命令行接口 可以被用于生成各种类,为你构建 Laravel 项目时节省大量手动输入的时间。在此例中,让我们使用 make:migration 命令为 tasks 数据表生成新的数据库迁移:
php artisan make:migration create_tasks_table --create=tasks
此迁移会被放置在你项目的 database/migrations 目录中。你可能已经注意到,make:migration 命令已经增加了自动递增的 ID 及时间戳至迁移文件。让我们编辑这个文件并为任务的名称增加额外的 string 字段,也增加连接 tasks 与 users 数据表的 user_id 字段:
<?php
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class CreateTasksTable extends Migration
/**
* 运行迁移。
* @return void
*/
public function up()
Schema::create('tasks', function (Blueprint $table) {
$table->increments('id');
$table->integer('user_id')->index();
$table->string('name');
$table->timestamps();
});
/**
* 还原迁移。
* @return void
*/
public function down()
Schema::drop('tasks');
我们可以使用 migrate Artisan 命令来运行迁移。如果你使用了 Homestead,则必须在虚拟机中运行这个命令,因为你的主机无法直接访问数据库:
php artisan migrate
这个命令会创建我们所有的数据表。如果你使用数据库客户端检查数据表,那么你应该看到新的 tasks 与 users 数据表,其中包含了我们迁移中所定义的字段。接着,我们已经准备好定义我们的 Eloquent ORM 模型!
Eloquent 模型
Eloquent 是 Laravel 默认的 ORM(对象关联映射)。Eloqunet 通过明确的定义「模型」,让你可以轻松的在数据库获取及保存数据。一般情况下,每个 Eloqunet 模型会直接对应一张数据表。
User 模型
首先,我们需要对应 users 数据表的模型。不过,如果你看过项目的 app 目录,你会发现 Laravel 已经附带了一个 User 模型,所以没必要去手动生成。
Task 模型
让我们定义一个对应至 tasks 数据表的 Task 模型。同样的,我们可以使用 Artisan 命令来生成此模型。在此例中,我们会使用 make:model 命令:
php artisan make:model Task
这个模型会放置到你应用程序的 app 目录中。默认情况下此模型类将是空的。我们不必明确告知 Eloquent 模型要对应哪张数据表,因为它会假设数据表是模型名称的复数型态。所以,在此例中,Task 模型会假设对应至 tasks 数据表。
让我们增加一些东西到模型上。首先,我们需要声明模型的 name 属性应该能被「批量赋值」:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Task extends Model
/**
* 这些属性能被批量赋值。
* @var array
*/
protected $fillable = ['name'];
在为我们的应用程序增加路由时,我们会学习更多关于如何使用 Eloquent 模型的知识。当然,你也可以随意参考 完整的 Eloquent 文档 来获取更多信息。
Eloquent 关联
现在我们的模型已经定义好了,这时候需要将他们链接在一起。例如,我们的 User 可以拥有多个 Task 实例,而一条 Task 则只能被赋给一名 User。定义好关联可以让我们很轻松的整理它们之间的关系,就像这样:
$user = App\User::find(1);
foreach ($user->tasks as $task) {
echo $task->name;
tasks 关联
首先,让我们在 User 模型定义 tasks 的关联。Eloquent 关联被定义为模型中的方法。Eloquent 支持多种不同类型的关联,所以请务必查阅 完整的 Eloquent 文档 以获取更多信息。在本例中,我们会在 User 模型中定义一个 tasks 函数,并调用 Eloquent 提供的 hasMany 方法:
<?php
namespace App;
// 导入的命名空间...
class User extends Model implements AuthenticatableContract,
AuthorizableContract,
CanResetPasswordContract
use Authenticatable, Authorizable, CanResetPassword;
// 其它的 Eloquent 属性...
/**
* 获取该用户的所有任务。
*/
public function tasks()
return $this->hasMany(Task::class);
user 关联
接着,让我们在 Task 模型定义 user 关联。同样的,我们会将此关联定义为模型中的方法。在本例中,我们会使用 Eloquent 提供的 belongsTo 方法来定义关联:
<?php
namespace App;
use App\User;
use Illuminate\Database\Eloquent\Model;
class Task extends Model
/**
* 这些属性能被批量赋值。
* @var array
*/
protected $fillable = ['name'];
/**
* 获取拥有此任务的用户。
*/
public function user()
return $this->belongsTo(User::class);
太棒了!现在我们的关联已经定义好了,可以开始构建我们的控制器啦!
路由
在我们任务清单应用程序的 基本版本 中,我们在 routes.php 中将所有逻辑都定义为闭包。对于大多数的应用程序来说,一般都会使用 控制器 来组织路由。控制器让我们将 HTTP 请求处理逻辑分散至多个文件以便进行更好的组织。
显示视图
我们只会有一个使用闭包的/ 路由,它是给应用程序访客的一个简单起始页面。所以,让我们先填写 / 路由。对于此路由,我们想渲染一个包含「欢迎」页面的 HTML 模板:
在 Laravel 里,所有的 HTML 模版都保存在 resources/views 目录,且我们可以在路由中使用 view 辅助函数来返回这些模版的其中一个:
Route::get('/', function () {
return view('welcome');
});
当然,我们必须明确定义好这些视图。这个将在稍后完成!
认证
我们需要让用户创建并登录帐号至我们的应用程序。一般来说,为网页应用程序构建完整的认证是相当乏味的工作。不过,因为它是一个通用的需求,所以 Laravel 试着让这个过程变得更轻松便捷。
首先,你会注意到在应用程序中已经包含一个 app/Http/Controllers/Auth/AuthController。这个控制器使用了特别的 AuthenticatesAndRegistersUsers trait,它包含了所有创建及认证用户的必要逻辑。
认证路由
所以,还有哪些部分是留给我们做的?我们依然需要创建注册及登录模板,并定义指向认证控制器的路由。首先,让我们在 app/Http/routes.php 文件中增加需要的路由:
// 认证路由...
Route::get('auth/login', 'Auth\AuthController@getLogin');
Route::post('auth/login', 'Auth\AuthController@postLogin');
Route::get('auth/logout', 'Auth\AuthController@getLogout');
// 注册路由...
Route::get('auth/register', 'Auth\AuthController@getRegister');
Route::post('auth/register', 'Auth\AuthController@postRegister');
认证视图
认证需要在 resources/views/auth 目录中创建 login.blade.php 与 register.blade.php。当然,这些视图的设计及样式并不重要;不过,它们至少得包含一些基本的字段。
register.blade.php 文件必需有一个包含 name、email、password 与 password_confirmation 字段的表单,并创建一个到 /auth/register 路由上的 POST 请求。
login.blade.php 文件必需有一个包含 email 与 password 字段的表单,并创建一个到 /auth/login 上的 POST 请求。
注意:如果你想查看这些视图的完整例子,可以在 GitHub 上获取 完整的源代码。
任务控制器
因为我们已经知道任务需要可被获取及保存,所以让我们使用 Artisan 命令行接口创建一个 TaskController,这个新的控制器会放置在 app/Http/Controllers 目录中:
php artisan make:controller TaskController --plain
现在这个控制器已经被生成,让我们继续在 app/Http/routes.php 文件中构建一些对应至此控制器的路由:
Route::get('/tasks', 'TaskController@index');
Route::post('/task', 'TaskController@store');
Route::delete('/task/{task}', 'TaskController@destroy');
认证所有的任务路由
对于此应用程序,我们希望所有的任务路由都需要一个认证的用户。换句话说,用户为了创建任务必须「登录至」应用程序中。所以,我们需要对任务路由进行限制,让其仅限已认证的用户访问。Laravel 使用 中间件 让这件事变得相当容易。
要让所有控制器中的行为要求已认证的用户,我们可以在控制器的构造器中增加 middleware 方法的调用。所以可用的路由中间件都被定义在 app/Http/Kernel.php 文件中。在本例中,我们希望为所有控制器的动作指派 auth 中间件:
<?php
namespace App\Http\Controllers;
use App\Http\Requests;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
class TaskController extends Controller
/**
* 创建一个新的控制器实例。
* @return void
*/
public function __construct()
$this->middleware('auth');
构建布局与视图
这个应用程序只会有一张视图,包含添加任务的表单,及目前所有任务的清单。为了帮助你想像此视图的画面,下方是完成后应用程序的截屏,采用了基本的 Bootstrap CSS 样式:
定义布局
几乎所有的网页应用程序都会在不同页面中共用相同的布局。举个例子,应用程序通常在每个页面(如果我们有一个以上页面)的顶部都拥有导航栏。Laravel 使用了 Blade 布局 来让不同页面共用这些相同的功能。
如同我们前面讨论的那样,Laravel 所有的视图都被保存在 resources/views。所以,让我们来定义一个新的布局视图至 resources/views/layouts/app.blade.php 中。.blade.php 扩展名会告知框架使用 Blade 模板引擎 渲染此视图。当然,你可以在 Laravel 使用纯 PHP 的模版。不过,Blade 提供了更方便的捷径来编写干净、简洁的模板。
我们的 app.blade.php 视图看起来应该如下面这样:
// resources/views/layouts/app.blade.php
<!DOCTYPE html>
<html lang="en">
<head>
<title>Laravel 快速入门 - 高级</title>
<!-- CSS 及 JavaScript -->
</head>
<body>
<div class="container">
<nav class="navbar navbar-default">
<!-- Navbar 内容 -->
</nav>
</div>
@yield('content')
</body>
</html>
注意布局中的 @yield('content') 部分。这是特殊的 Blade 命令,让子页面可以在此处注入自己的内容以扩展布局。接着,让我们定义将会使用此布局并提供主要内容的子视图。
定义子视图
很好,我们的应用程序布局已经完成。接下来,我们需要定义包含创建任务的表单,及列出已有任务数据库表的视图。让我们将此视图定义在 resources/views/tasks/index.blade.php,它会对应至我们 TaskController 的 index 方法。
我们会跳过一些 Bootstrap CSS 模版,只专注在重要的事物上。你可以在 GitHub 下载到应用程序的完整源代码:
// resources/views/tasks/index.blade.php
@extends('layouts.app')
@section('content')
<!-- Bootstrap 模版... -->
<div class="panel-body">
<!-- 显示验证错误 -->
@include('common.errors')
<!-- 新任务的表单 -->
<form action="/task" method="POST" class="form-horizontal">
{{ csrf_field() }}
<!-- 任务名称 -->
<div class="form-group">
<label for="task-name" class="col-sm-3 control-label">任务</label>
<div class="col-sm-6">
<input type="text" name="name" id="task-name" class="form-control">
</div>
</div>
<!-- 增加任务按钮-->
<div class="form-group">
<div class="col-sm-offset-3 col-sm-6">
<button type="submit" class="btn btn-default">
<i class="fa fa-plus"></i> 增加任务
</button>
</div>
</div>
</form>
</div>
<!-- 待办:目前任务 -->
@endsection
一些注意事项的说明
在继续开始之前,让我们先来谈谈有关模板的一些注意事项。首先 @extends 命令会告知 Blade,我们使用了定义于 resources/views/layouts/app.blade.php 的布局。所有在 @section('content') 及 @endsection 之间的内容都会被注入到 app.blade.php 布局中的 @yield('content') 位置里。
现在我们已经为我们的应用程序定义了基本的布局及视图。接着让我们在 TaskController 的 index 方法返回此视图:
/**
* 显示用户所有任务的清单。
* @param Request $request
* @return Response
*/
public function index(Request $request)
return view('tasks.index');
接着,我们已经准备好增加代码至我们的 POST /task 路由的控制器方法内,以处理接收到的表单输入并增加新的任务至数据库中。
注意:@include('common.errors') 命令会加载位于 resources/views/common/errors.blade.php 的模板。我们尚未定义此模板,但是我们将会在后面定义它!
增加任务
验证
现在我们视图中已经有一个表单,我们需要增加代码至我们的 TaskController@store 方法来验证接收到的表单输入并创建新的任务。首先,让我们先来验证表单输入。
对此表单来说,我们要让 name 字段为必填,且它必须少于 255 字符。如果验证失败,我们会将用户重定向回 / URL,并将旧的输入及错误消息闪存至 session 中:
/**
* 创建新的任务。
* @param Request $request
* @return Response
*/
public function store(Request $request)
$this->validate($request, [
'name' => 'required|max:255',
]);
// 创建该任务...
如果你看过 基本快速入门指南,你会注意到验证的代码相比起来有些不同!这是因为在控制器内可以使用 Laravel 基底控制器所包含的 ValidatesRequests trait。这个 trait 提供了一个简单的 validate 方法,此方法可接收一个请求和包含验证规则的数组。
当验证失败时我们无需再手动重定向。如果指定的规则验证失败,用户会自动被重定向回原本的位置,并自动将错误消息闪存至 session 中。
$errors 变量
我们在视图中使用了 @include('common.errors') 命令来渲染表单的错误验证消息。common.errors 让我们可以简单的在所有的页面都显示相同格式的错误验证消息。现在让我们定义此视图的内容:
// resources/views/common/errors.blade.php
@if (count($errors) > 0)
<!-- 表单错误清单 -->
<div class="alert alert-danger">
<strong>哎呀!出了些问题!</strong>
<br><br>
<ul>
@foreach ($errors->all() as $error)
<li>{{ $error }}</li>
@endforeach
</ul>
</div>
@endif
注意:errors 变量可用于 每个 Laravel 的视图中。如果没有错误验证消息存在,那么它就会是一个空的 ViewErrorBag 实例。
创建任务
现在输入已经被验证处理完毕。让我们继续填写我们的路由来实际的创建一条新的任务。一旦新的任务被创建,我们便会将用户重定向回 /tasks URL。我们会充分的利用 Eloquent 的关联功能来创建该任务。
Laravel 大部分的关联提供了一个 create 方法,它接收一个包含属性的数组,并会在保存至数据库前自动设置关联模型的外键值。在此例中,create 方法会自动将指定任务的 user_id 属性设置为目前已验证用户的 ID,因为我们通过 $request->user() 访问。
/**
* 创建新的任务。
* @param Request $request
* @return Response
*/
public function store(Request $request)
$this->validate($request, [
'name' => 'required|max:255',
]);
$request->user()->tasks()->create([
'name' => $request->name,
]);
return redirect('/tasks');
太棒了!现在可以成功的创建任务了。接着,让我们继续构建已有的任务清单,并增加至我们的视图中。
显示已有的任务
首先,我们需要编辑我们的 TaskController@index 方法,以传递所有已有的任务到此视图上。view 函数接收一个能在视图中取用的数据数组作为第二个参数,数组中的每个键都会在视图中作为变量。就像这样:
/**
* 显示用户的所有任务清单。
* @param Request $request
* @return Response
*/
public function index(Request $request)
$tasks = Task::where('user_id', $request->user()->id)->get();
return view('tasks.index', [
'tasks' => $tasks,
]);
不过,让我们先来探讨一些 Laravel 的依赖注入功能,来将 TaskRepository 注入至我们的 TaskController,我们将会通过它来访问所有的数据。
依赖注入
Laravel 的 服务容器 是整个框架中最强大的功能之一。在读完本快速上手之后,请务必阅读容器文档的全部内容。
创建资源库
如前面所提,我们希望定义一个 TaskRepository 存放所有 Task 模型的数据访问逻辑。当应用程序扩增时,在整个应用程序中共用同样的 Eloquent 查找将会是相当有用的。
所以,让我们先来创建一个 app/Repositories 目录,并增加 TaskRepository 类。切记,Laravel 的 app 中所有的文件夹会自动加载并使用 PSR-4 自动加载标准,所以你可以随意创建许多额外目录。
<?php
namespace App\Repositories;
use App\User;
use App\Task;
class TaskRepository
/**
* 获取指定用户的所有任务。
* @param User $user
* @return Collection
*/
public function forUser(User $user)
return Task::where('user_id', $user->id)
->orderBy('created_at', 'asc')
->get();
注入资源库
一旦我们的资源库定义完成,我们就可以在 TaskController 控制器的构造器中对它使用「类型提示」,并在我们的 index 路由中使用它。因为 Laravel 使用容器来解析所有的控制器,所以我们的依赖会自动被注入至控制器的实例中:
<?php
namespace App\Http\Controllers;
use App\Task;
use App\Http\Requests;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
use App\Repositories\TaskRepository;
class TaskController extends Controller
/**
* 任务资源库的实例。
* @var TaskRepository
*/
protected $tasks;
/**
* 创建新的控制器实例。
* @param TaskRepository $tasks
* @return void
*/
public function __construct(TaskRepository $tasks)
$this->middleware('auth');
$this->tasks = $tasks;
/**
* 获取指定用户的所有任务。
* @param Request $request
* @return Response
*/
public function index(Request $request)
return view('tasks.index', [
'tasks' => $this->tasks->forUser($request->user()),
]);
显示任务
一旦数据被传递,我们将在 tasks/index.blade.php 视图中将任务切分并将它们显示至数据库表中。@foreach 命令结构让我们可以编写简洁的循环语句,并编译成快速的纯 PHP 代码:
@extends('layouts.app')
@section('content')
<!-- 创建任务表单... -->
<!-- 目前任务 -->
@if (count($tasks) > 0)
<div class="panel panel-default">
<div class="panel-heading">
目前任务
</div>
<div class="panel-body">
<table class="table table-striped task-table">
<!-- 表头 -->
<thead>
<th>Task</th>
<th> </th>
</thead>
<!-- 表身 -->
<tbody>
@foreach ($tasks as $task)
<tr>
<!-- 任务名称 -->
<td class="table-text">
<div>{{ $task->name }}</div>
</td>
<td>
<!-- 待办:删除按钮 -->
</td>
</tr>
@endforeach
</tbody>
</table>
</div>
</div>
@endif
@endsection
我们的任务应用大部分都完成了。但是,当我们完成已有的任务后,还没有任何方式可以删除它们。接着让我们来增加此功能!
删除任务
增加删除按钮
我们在我们的代码中应该放删除按钮的地方放了「待办」的注释。所以,让我们在 tasks/index.blade.php 视图中列出任务的每一行增加一个删除按钮。我们会为列表中的每个任务创建一个只有单个按钮的小表单。当按钮被按下时,一个 DELETE /task 的请求将会被发送到应用程序,它会触发我们的 TaskController@destroy 方法:
<tr>
<!-- 任务名称 -->
<td class="table-text">
<div>{{ $task->name }}</div>
</td>
<!-- 删除按钮 -->
<td>
<form action="/task/{{ $task->id }}" method="POST">
{{ csrf_field() }}
{{ method_field('DELETE') }}
<button>删除任务</button>
</form>
</td>
</tr>
表单方法伪造
注意,删除按钮的表单 method 被列为 POST,即使我们响应的请求使用了 Route::delete 路由。HTML 表单只允许 GET 及 POST HTTP 动词,所以我们需要有个方式在表单假冒一个 DELETE 请求。
我们可以在表单中通过 method_field('DELETE') 函数输出的结果假冒一个 DELETE 请求。此函数会生成一个隐藏的表单输入,Laravel 会辨识并覆盖掉实际使用的 HTTP 请求方法。生成的字段看起来如下:
<input type="hidden" name="_method" value="DELETE">
路由模型绑定
现在,我们大致上已经准备好定义我们 TaskController 的 destroy 方法。但是首先,让我们重新检查我们为它声明的路由:
Route::delete('/task/{task}', 'TaskController@destroy');
无需添加任何额外的代码,Laravel 便会将指定的任务 ID 注入至 TaskController@destroy 方法中,如下:
/**
* Destroy the given task.
* @param Request $request
* @param string $taskId
* @return Response
*/
public function destroy(Request $request, $taskId)
//
但是,我们要在这个方法中做的第一件事,就是通过指定的 ID 从数据库中获取 Task 实例。所以,如果 Laravel 可以先注入与 ID 符合的 Task 实例,那岂不是很棒?让我们来做到这一点!
在你的 app/Providers/RouteServiceProvider.php 文件的 boot 方法中,增加下方这行代码:
$router->model('task', 'App\Task');
这一小行的代码会告知 Laravel,若在路由声明中看见 {task},就会获取与指定 ID 对应的 Task 模型。现在我们可以定义我们的 destroy 方法,如下:
/**
* 卸除指定的任务。
* @param Request $request
* @param Task $task
* @return Response
*/
public function destroy(Request $request, Task $task)
//
认证
现在,我们有一个注入至 destroy 方法的 Task 实例;然而,我们不能保证通过认证的用户实际上「拥有」指定的任务。举个例子,一个恶意的请求可能通过传递一个随机任务 ID 至 /tasks/{task} URL,企图尝试删除其他用户的任务。所以,我们需要使用 Laravel 的授权功能,以确保只有已认证的用户才能注入路由的 Task 实例。
创建一个授权策略
Laravel 使用了「授权策略」将授权逻辑组织至简单,小型的类。一般来说,每个授权策略会对应至一个模型。所以,让我们使用 Artisan 命令行接口创建一个 TaskPolicy,生成的文件会被放置于 app/Policies/TaskPolicy.php:
php artisan make:policy TaskPolicy
接着,让我们给授权策略增加一个 destroy 方法。此方法会获取一个 User 实例及一个 Task 实例。此方法会简单的检查当用户的 ID 是否是任务的 user_id,也就是说是不是作者。实际上,所有的授权方法都必须返回 true 或 false:
<?php
namespace App\Policies;
use App\User;
use App\Task;
use Illuminate\Auth\Access\HandlesAuthorization;
class TaskPolicy
use HandlesAuthorization;
/**
* 判断指定用户是否可以删除指定的任务。
* @param User $user
* @param Task $task
* @return bool
*/
public function destroy(User $user, Task $task)
return $user->id === $task->user_id;
最后,我们需要将 Task 模型与 TaskPolicy 进行连接。可以通过在 app/Providers/AuthServiceProvider.php 文件增加一行 $policies 属性做到这件事。这会告知 Laravel,当我们尝试授权 Task 实例的行为时该用哪个授权策略:
/**
* 应用程序的授权策略对应。
* @var array
*/
protected $policies = [
Task::class => TaskPolicy::class,
];
授权行为
现在我们的授权策略已经编写完毕,让我们在 destroy 方法中使用它。Laravel 所有的控制器都可以调用一个 authorize 方法,它由 AuthorizesRequest trait 所提供:
/**
* 卸除指定的任务。
* @param Request $request
* @param Task $task
* @return Response
*/
public function destroy(Request $request, Task $task)
$this->authorize('destroy', $task);
// 删除该任务...
让我们花点时间看看此方法的调用。传递至 authorize 的第一个参数是我们希望调用的授权策略方法名称。第二个参数是我们目前有关的模型实例。切记,我们已经告诉 Laravel 我们的 Task 模型会对应至我们的 TaskPolicy,所以框架会知道该触发哪个授权策略的 destroy 方法。当前用户会被自动发送至授权方法中,所以我们不必在此手动传递它。
如果该行为被授权了,我们的代码就会继续正常运行。但是,如果该行为不被授权(意指授权策略的 destroy 方法返回 false),就会自动被抛出一个 403 异常并将错误页面显示给用户。
注意:Laravel 提供的授权服务还有很多种其它的方式可供交互。请务必浏览完整的 授权文档。
删除该任务
最后,让我们完成增加逻辑至我们的 destroy 方法来实际删除指定的任务。我们可以使用 Eloquent 的 delete 方法从数据库中删除指定的模型实例。一旦记录被删除,我们将会把用户重定向回 tasks URL:
/**
* 删除指定的任务。
* @param Request $request
* @param Task $task
* @return Response
*/
public function destroy(Request $request, Task $task)
$this->authorize('destroy', $task);
$task->delete();
return redirect('/tasks');
本文章首发在 LearnKu.com 网站上。
上一篇
下一篇
Markdown 文本
纠错改进
《L05 电商实战》
从零开发一个电商项目,功能包括电商后台、商品 & SKU 管理、购物车、订单管理、支付宝支付、微信支付、订单退款流程、优惠券等
《G01 Go 实战入门》
从零开始带你一步步开发一个 Go 博客项目,让你在最短的时间内学会使用 Go 进行编码。项目结构很大程度上参考了 Laravel。
推荐文章:
更多推荐...
博客
用Go实现支持多种协议的抓包工具——Shermie-Proxy
22
33
5个月前
博客
国密招商银行对接
29
23
6个月前
博客
php开发的js逆向rpc框架
15
7个月前
博客
强一致性的分布式事务几种模式对比(php有了新方案)
31
19
1年前
博客
基于DTM分布式事务管理的PHP客户端
16
1年前
博客
Laravel基于RT模式实现分布式事务(突破技术支持子服务嵌套事务)
81
39
1年前
讨论数量: 0
发起讨论
只看当前版本
暂无话题~
社区赞助商
成为赞助商
关于 LearnKu
LearnKu 是终身编程者的修道场
做最专业、严肃的技术论坛
LearnKu 诞生的故事
资源推荐
《社区使用指南》
《文档撰写指南》
《LearnKu 社区规范》
《提问的智慧》
服务提供商
其他信息
成为版主
所有测验
联系站长(反馈建议)
粤ICP备18099781号-6
粤公网安备 44030502004330号
违法和不良信息举报
由 Summer 设计和编码 ❤
请登录
提交
忘记密码?
or
注册
第三方账号登录
微信登录
GitHub 登录
内容举报
匿名举报,为防止滥用,仅管理员可见举报者。
我要举报该,理由是:
垃圾广告:恶意灌水、广告、推广等内容
无意义内容:测试、灌水、文不对题、消极内容、文章品质太差等
违规内容:色情、暴利、血腥、敏感信息等
不友善内容:人身攻击、挑衅辱骂、恶意行为
科学上网:翻墙、VPN、Shadowsocks,政策风险,会被关站!
不懂提问:提问太随意,需要再做一遍《提问的智慧》测验
随意提问:提问没有发布在社区问答分类下
排版混乱:没有合理使用 Markdown 编写文章,未使用代码高亮
内容结构混乱:逻辑不清晰,内容混乱,难以阅读
标题随意:标题党、标题不释义
尊重版权:分享付费课程、破解软件(付费),侵犯作者劳动成果
其他理由:请补充说明
举报
取消