laravel 学习指南 第四章
- TOC
 {:toc}
4 快速入门进阶版
4.1. 安装
4.1.1 使用composer
$ composer create-project laravel/laravel quickstart --prefer-dist
4.1.2 使用git克隆完整包
$ git clone https://github.com/laravel/quickstart-intermediate quickstart
$ cd quickstart
$ composer install
$ php artisan migrate
4.2 准备数据库
4.2.1 数据迁移
需要用到users表与tasks表。
users表的已经在database/migratiions目录下。
tasks表,需要使用命令创建一个:
$ php artisan make:migration create_tasks_table --create=tasks
在生成的文件中加入
| 1 | $table->integer('user_id')->index(); | 
->index()标识增加索引。user_id用于建立tasks表与user表之间的关联。
使用下方命令导入数据库
$ php artisan migrate
4.2.2 Eloquent模型
user模型
laravel中自带了user模块。
Task模型
使用下方命令创建task模型。
$ php artisan make:model Task
在Task模型中,声明name属性支持批量赋值。
批量赋值:将一个数组发送到模型类用于创建新模型实例是使用。
laravel有两种批量赋值属性,一种是$fillable可以通过批量赋值进行赋值。另一种是$guarded在批量赋值时会被过滤掉。
添加到app/Task.php
protected $fillable = ['name'];
4.2.3 Eloquent关联关系
tasks关联关系
在user模型中定义tasks关联关系。这里使用一对多关系,laravel的ELoquent中提供了hasMany方法。
在app/user.php文件中添加:
use App\Task;
public function tasks()
{
    return $this->hasMany(Task::class);
}
user关联关系
要定义与hasMany相对的关联关系,需要在子模型中定义一个关联方法去调用belongsTo方法:
添加到app/Task.php
use App\User;
public function user()
{
    return $this->belongsTo(User::class);
}
4.3 路由
在routes.php中可以使用闭包定义所有的业务逻辑。实际上,大部分应用都会使用控制器来组织路由。
4.3.1 显示视图
使用view函数从路由中返回一个模板:
| 1 | Route::get('/', function () { | 
4.3.2 用户认证
web中用户认证工作是非常乏味的,laravel提供一个auth组件让他变得轻松。
可以直接使用Artisan指令做完成auth的创建。
$ php artisan make:auth --views
随后只需要将auth添加到路由列表。
| 1 | Route::auth(); | 
4.3.3 任务控制器
接下来建立TaskController控制器,来处理任务。默认情况下控制器放置在app/Http/controllers目录下。使用下方命令创建:
$ php artisan make:controller TaskController
现在添加一些对应控制器的路由,在app/Http/routes.php中添加:
| 1 | Route::get('/tasks', 'TaskController@index'); | 
设置所有任务路由需要登录才能访问
我们希望用户必须登陆到系统才能创建新任务。所以需要限制访问用户,为登陆用户。
laravel使用中间件来处理这种限制。
| 1 | public function __construct() | 
4.4 创建布局与视图
布局方案与之前的版本相同。

4.4.1 定义布局
共用模板在resources/views/layouts/app.blade.php。
@yield('content')为使用blade模板要插入的功能模块。
4.4.2 定义子视图
随后定义resources/views/tasks/index.blade.php。它会对应TaskController控制器的index方法。
随后在TaskController控制其中添加index方法的返回视图。
| 1 | 
 | 
4.5 添加任务
4.5.1 验证表单输入
编写TaskController@store路由对应的处理方法,处理一个表单请求并创建一个新任务。
| 1 | public function store(Request $request){ | 
在控制器中,可以直接使用ValidatesRequests类中的validate方法。
而不用手动判断验证失败后的重定向,如果验证失败,用户会自动被重定向到来源页面,而错误信息也会存放到一次性Session中。
$errors
使用@include('common.errors')来渲染表单验证错误信息。
文件位置resources/views/common/errors.blade.php
| 1 | @if (count($errors) > 0) | 
4.5.2 创建任务
验证完成后,要新建一个任务。当任务新建完成,页面会跳转到/tasks。
laravel的关联提供了save方法,该方法接收一个关联模型实例,并且会在保存的数据库之前自动设置外键值到关联模型上。
这里save方法会自动将当前用户的,用户ID赋予给定的user_id属性。通过$request->user()获取当前用户实例:
| 1 | $request->user()->tasks()->create([ | 
4.6 显示己存在的任务
现在需要编辑TaskController@index传递所有已存在任务到视图。view函数接收一个数组作为第二个参数,数组中的每个值都会在视图中作为变数。
| 1 | public function index(Request $request) | 
4.6.1 依赖注入
laravel的服务容器是整个框架中最重要的特性。
创建Repository
正如之前说的,我们要定义一个TaskRepository来处理所有对Task模式的数据访问,随着应用的增长,需要在应用中共享一些Eloquent查询时,就变得特别有用。
创建app/Repositories目录并在其中创建一个TaskRepository类。记住,laravel项目的app文件夹下的所有目录都是使用PSR-4自动加载标准,所以可以随意创建需要的目录:
| 1 | 
 | 
注入Repository
Repository创建好之后,通过在TaskController的构造函数以类型提示的方式注入该Repository,然后就可以在index方法中使用。
由于laravel使用容器来解析所有控制器,所以依赖会被自动注入到控制器:
| 1 | 
 | 
4.6.2 显示任务
在tasks/index.blade.php中以表格形式显示所有任务。Blade中使用@foreach处理循环数据。
4.7 删除任务
4.7.1 添加删除按钮
当一个DELETE /task请求被发送到应用,它会触发TaskController@destroy方法:
在表单中同样要使用方法欺骗。
4.7.2 路由模型绑定
定义TaskController的destroy方法。但是首先,重新查看路由的定义以及控制器方法。
4.7.3 用户授权
现在要将Task实例注入到destroy方法。然而为了保证当前登录用户是给定任务的用。
例如:一些恶意请求可能尝试通过传统随机任务ID到/tasks/{task}链接删除另一个用户的任务。
所有需要使用laravel的授权功能来确保,当前登录用户拥有操作Task实例的权限。
创建Policy
laravel使用策略来将授权组织到单个类中,通常,每个策略都对应一个模型。
因此,使用Artisan命令创建一个TaskPolicy,生成的文件位于app/Policies/TaskPolicy.php:
$ php artisan make:policy TaskPolicy
随后将destroy方法添加到策略中,该方法会获取一个user实例和task实例,检查用户ID和任务的user_id是否相同。
实际上,所有的策略方法都会返回true或false:
| 1 | 
 | 
最后,需要关联Task模型和TaskPolicy,通过在app/Providers/AuthServiceProvider.php的policies属性添加注册实现。
注册后会告知Laravel无论何时尝试授权到Task实例时,该使用哪个策略类进行判断:
| 1 | protected $policies = [ | 
授权动作
编写好策略后,在destroy方法中使用它。所有的laravel控制器都可以调用authorize方法,该方法由AuthorizesRequest提供:
app/Controllers/TaskController.php文件。
| 1 | public function destroy(Request $request, Task $task){ | 
4.7.4 删除任务
最后在destroy方法中实际删除任务。使用Eloquent的delete方法从数据库中删除给定的模型实例。
删除后返回/tasks连接:
app/Controllers/TaskController.php文件中完整的TaskController@destroy方法。
| 1 | public function destroy(Request $request, Task $task){ |