在实际应用中,订单类型的操作会很多,如订单操作中的订单创建、列表显示、删除、修改、分页等,本章以此为例,简要介绍其在Laravel中的应用。
此文借鉴了Laravel的quickshtart。
本文项目的GitHub地址为:GitHub地址,可参考。
基本MVC实例
创建模型
使用Artisan创建Model:1
php artisan make:model Task
任务与任务的创建者相关,因此,默认只显示当前用户对应的任务,故TaskModel为: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可根据前端的需求调整。