在实际应用中,订单类型的操作会很多,如订单操作中的订单创建、列表显示、删除、修改、分页等,本章以此为例,简要介绍其在Laravel中的应用。
此文借鉴了Laravel的quickshtart。
本文项目的GitHub地址为:GitHub地址,可参考。
基本MVC实例
创建模型
使用Artisan
创建Model:1
php artisan make:model Task
任务与任务的创建者相关,因此,默认只显示当前用户对应的任务,故Task
Model为:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33<?php
namespace App;
use App\User;
use Illuminate\Database\Eloquent\Model;
class Task extends Model
{
/**
* The attributes that are mass assignable.
*
* @var array
*/
protected $fillable = ['name'];
/**
* The attributes that should be cast to native types.
*
* @var array
*/
protected $casts = [
'user_id' => 'int',
];
/**
* Get the user that owns the task.
*/
public function user()
{
return $this->belongsTo(User::class);
}
}
创建控制器
使用Artisan
创建Controller:1
php artisan make:controller TaskController
将task相关的所有请求路由到TaskController中,因此,在routes.php
中增加task的resource:1
2
3
4
5Route::group(['middleware' => ['web']], function () {
Route::resource('task', 'TaskController');
Route::resource('user', 'UserController');
Route::auth();
});
在Controller中,定义获取list、创建、删除的方法,根据Laravel Controller定义分别为index
、store
、destroy
,实现如下:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Http\Requests;
use App\Http\Controllers\Controller;
use App\Task;
class TaskController extends Controller
{
/**
* Display a list of all of the user's task.
*
* @param Request $request
* @return Response
*/
public function index(Request $request)
{
return view('tasks.index', [
'tasks' => Task::orderBy('created_at', 'asc')->get()
]);
}
/**
* Create a new task.
*
* @param Request $request
* @return Response
*/
public function store(Request $request)
{
$validator = Validator::make($request->all(), [
'name' => 'required|max:255',
]);
if ($validator->fails()) {
return redirect('/tasks')
->withInput()
->withErrors($validator);
}
$task = new Task;
$task->name = $request->name;
$task->save();
return redirect('/tasks');
}
/**
* Destroy the given task.
*
* @param Request $request
* @param Task $task
* @return Response
*/
public function destroy(Request $request, Task $task)
{
Task::findOrFail($id)->delete();
return redirect('/tasks');
}
}
创建视图
根据Controller中的定义,定义默认task的视图。在resources/views
下创建tasks
的文件夹,然后在其中创建index.blade.php
的文件,其内容为:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78@extends('layouts.app')
@section('content')
<div class="container">
<div class="col-sm-offset-2 col-sm-8">
<div class="panel panel-default">
<div class="panel-heading">
New Task
</div>
<div class="panel-body">
<!-- Display Validation Errors -->
@include('common.errors')
<!-- New Task Form -->
<form action="/task" method="POST" class="form-horizontal">
{{ csrf_field() }}
<!-- Task Name -->
<div class="form-group">
<label for="task-name" class="col-sm-3 control-label">Task</label>
<div class="col-sm-6">
<input type="text" name="name" id="task-name" class="form-control" value="{{ old('task') }}">
</div>
</div>
<!-- Add Task Button -->
<div class="form-group">
<div class="col-sm-offset-3 col-sm-6">
<button type="submit" class="btn btn-default">
<i class="fa fa-btn fa-plus"></i>Add Task
</button>
</div>
</div>
</form>
</div>
</div>
<!-- Current Tasks -->
@if (count($tasks) > 0)
<div class="panel panel-default">
<div class="panel-heading">
Current Tasks
</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>
<!-- Task Delete Button -->
<td>
<form action="/task/{{ $task->id }}" method="POST">
{{ csrf_field() }}
{{ method_field('DELETE') }}
<button type="submit" id="delete-task-{{ $task->id }}" class="btn btn-danger">
<i class="fa fa-btn fa-trash"></i>Delete
</button>
</form>
</td>
</tr>
@endforeach
</tbody>
</table>
</div>
</div>
@endif
</div>
</div>
@endsection
此处将创建人物、列表展示以及删除人物均整合到该页面中。
同时,在app.blade.php
中删除冗余的侧边栏导航,增加Tasks
的导航。
如此,点击侧边栏的Tasks
,可看到页面:
其中数据通过seed填充。
基本MVC进阶
在用户登录及管理章节中,我们使用了Repository。同时,对于删除操作,一般而言,只允许该任务的创建者才拥有删除权限,因此,此处对以上的流程稍作优化。
创建Repository
在app/Repositories
中创建TaskRepository.php
,在其中使用用户权限管理,即为:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22<?php
namespace App\Repositories;
use App\User;
use App\Task;
class TaskRepository
{
/**
* Get all of the tasks for a given user.
*
* @param User $user
* @return Collection
*/
public function forUser(User $user)
{
return Task::where('user_id', $user->id)
->orderBy('created_at', 'asc')
->get();
}
}
使用auth控制删除
首先在app/Policies
中创建TaskPlolicy.php
,限制destroy
方法:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24<?php
namespace App\Policies;
use App\User;
use App\Task;
use Illuminate\Auth\Access\HandlesAuthorization;
class TaskPolicy
{
use HandlesAuthorization;
/**
* Determine if the given user can delete the given task.
*
* @param User $user
* @param Task $task
* @return bool
*/
public function destroy(User $user, Task $task)
{
return $user->id === $task->user_id;
}
}
然后在app/Providers/AuthServiceProvider.php
中添加到$policies
中:1
2
3protected $policies = [
'App\Task' => 'App\Policies\TaskPolicy',
];
如此,可在Controller中使用。
改造Controller
在以上Repository和Policy基础上,改造Controller,如下:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Http\Requests;
use App\Http\Controllers\Controller;
use App\Task;
use App\Repositories\TaskRepository;
class TaskController extends Controller
{
/**
* The task repository instance.
*
* @var TaskRepository
*/
protected $tasks;
/**
* Create a new controller instance.
*
* @param TaskRepository $tasks
* @return void
*/
public function __construct(TaskRepository $tasks)
{
$this->middleware('auth');
$this->tasks = $tasks;
}
/**
* Display a list of all of the user's task.
*
* @param Request $request
* @return Response
*/
public function index(Request $request)
{
return view('tasks.index', [
'tasks' => $this->tasks->forUser($request->user()),
]);
}
/**
* Create a new task.
*
* @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('/task');
}
/**
* Destroy the given task.
*
* @param Request $request
* @param Task $task
* @return Response
*/
public function destroy(Request $request, Task $task)
{
$this->authorize('destroy', $task);
$task->delete();
return redirect('/task');
}
}
其中通过构造方法注入Repository,并使用$this->authorize(‘destroy’, $task)
判断删除操作时候被授权,若未被授权,则该操作终止。
分页
当任务太过,上百甚至上千时,需要使用分页显示。Laravel中自带了分页功能,可通过该功能快速地实现分页,以及下一页等的URL,同时提供了前端显示的基于Bootstrap的demo。
Laravel提供了paginate
方法用于分页,可在query builder以及Eloquent query中使用。如以上实例中,需要对分页显示20条数据,则将TaskRepository
中的方法改为:1
2
3
4
5
6public function forUser(User $user)
{
return Task::where('user_id', $user->id)
->orderBy('created_at', 'asc')
->paginate(20);
}
增加paginate
方法。
增加之后,可看到返回的数据中增加了分页信息,如示例所示:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82{
"total": 23273,
"per_page": 10,
"current_page": 1,
"last_page": 1164,
"next_page_url": "http://localhost/task?page=2",
"prev_page_url": null,
"from": 1,
"to": 20,
"data": [
{
"id": 3,
"user_id": 1,
"name": "damye test task",
"created_at": "2016-03-18 09:01:07",
"updated_at": "2016-03-18 09:01:07"
},
{
"id": 4,
"user_id": 1,
"name": "test controller",
"created_at": "2016-03-18 10:06:36",
"updated_at": "2016-03-18 10:06:36"
},
{
"id": 5,
"user_id": 1,
"name": "432342",
"created_at": "2016-03-18 10:09:53",
"updated_at": "2016-03-18 10:09:53"
},
{
"id": 6,
"user_id": 1,
"name": "PejSLfbKwV",
"created_at": "2016-03-29 08:04:30",
"updated_at": "2016-03-29 08:04:30"
},
{
"id": 7,
"user_id": 1,
"name": "mAfmaBCsUS",
"created_at": "2016-03-29 08:04:30",
"updated_at": "2016-03-29 08:04:30"
},
{
"id": 17,
"user_id": 1,
"name": "VbVV5J7VvH",
"created_at": "2016-03-29 08:04:31",
"updated_at": "2016-03-29 08:04:31"
},
{
"id": 18,
"user_id": 1,
"name": "XQwXK9BeGE",
"created_at": "2016-03-29 08:04:31",
"updated_at": "2016-03-29 08:04:31"
},
{
"id": 19,
"user_id": 1,
"name": "3JhnyOLMgQ",
"created_at": "2016-03-29 08:04:31",
"updated_at": "2016-03-29 08:04:31"
},
{
"id": 20,
"user_id": 1,
"name": "fGx83BzjU6",
"created_at": "2016-03-29 08:04:31",
"updated_at": "2016-03-29 08:04:31"
},
{
"id": 21,
"user_id": 1,
"name": "9Az4ctR7lb",
"created_at": "2016-03-29 08:04:31",
"updated_at": "2016-03-29 08:04:31"
}
]
}
如此,后台返回的数据已带上分页信息。Laravel同时提供了基于Bootstrap的前端代码,在前端加上:1
{!! $tasks->links() !!}
即可获得页码信息。
示例如图:
总结
本文的方法中,将任务的创建、列表展示、删除合为一个页面,实际处理的时候可根据需求拆分,使用方法类似。
另外,css和js可根据前端的需求调整。