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 2 $table ->integer ('user_id' )->index ();$table ->string ('name' );
->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 2 3 Route ::get ('/' , function () { return view ('welcome' ); });
4.3.2 用户认证 web中用户认证工作是非常乏味的,laravel提供一个auth组件让他变得轻松。
可以直接使用Artisan指令做完成auth的创建。
$ php artisan make:auth --views
随后只需要将auth添加到路由列表。
4.3.3 任务控制器 接下来建立TaskController控制器,来处理任务。默认情况下控制器放置在app/Http/controllers目录下。使用下方命令创建:
$ php artisan make:controller TaskController
现在添加一些对应控制器的路由,在app/Http/routes.php中添加:
1 2 3 Route ::get ('/tasks' , 'TaskController@index' );Route ::post ('/task' , 'TaskController@store' );Route ::delete ('/task/{task}' , 'TaskController@destroy' );
设置所有任务路由需要登录才能访问
我们希望用户必须登陆到系统才能创建新任务。所以需要限制访问用户,为登陆用户。
laravel使用中间件来处理这种限制。
1 2 3 4 public function __construct ( ) { $this ->middleware ('auth' ); }
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 2 3 4 5 6 public function index (Request $request ) { return view ('tasks.index' ); }
4.5 添加任务 4.5.1 验证表单输入 编写TaskController@store路由对应的处理方法,处理一个表单请求并创建一个新任务。
1 2 3 4 5 6 7 public function store (Request $request ) { $this ->validate ($request , [ 'name' => 'required|max:255' , ]); }
在控制器中,可以直接使用ValidatesRequests类中的validate方法。
而不用手动判断验证失败后的重定向,如果验证失败,用户会自动被重定向到来源页面,而错误信息也会存放到一次性Session中。
$errors
使用@include('common.errors')来渲染表单验证错误信息。
文件位置resources/views/common/errors.blade.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 @if (count($errors) > 0) <div class ="alert alert-danger" > <strong > Whoops! Something went wrong!</strong > <br > <br > <ul > @foreach ($errors->all() as $error) <li > {{ $error }}</li > @endforeach </ul > </div > @endif
4.5.2 创建任务 验证完成后,要新建一个任务。当任务新建完成,页面会跳转到/tasks。
laravel的关联提供了save方法,该方法接收一个关联模型实例,并且会在保存的数据库之前自动设置外键值到关联模型上。
这里save方法会自动将当前用户的,用户ID赋予给定的user_id属性。通过$request->user()获取当前用户实例:
1 2 3 4 5 $request ->user ()->tasks ()->create ([ 'name' => $request ->name, ]); return redirect ('/tasks' );
4.6 显示己存在的任务 现在需要编辑TaskController@index传递所有已存在任务到视图。view函数接收一个数组作为第二个参数,数组中的每个值都会在视图中作为变数。
1 2 3 4 5 6 7 8 public function index (Request $request ) { $tasks = Task ::where ('user_id' , $request ->user ()->id)->get (); return view ('tasks.index' , [ 'tasks' => $tasks , ]); }
4.6.1 依赖注入 laravel的服务容器是整个框架中最重要的特性。
创建Repository
正如之前说的,我们要定义一个TaskRepository来处理所有对Task模式的数据访问,随着应用的增长,需要在应用中共享一些Eloquent查询时,就变得特别有用。
创建app/Repositories目录并在其中创建一个TaskRepository类。记住,laravel项目的app文件夹下的所有目录都是使用PSR-4自动加载标准,所以可以随意创建需要的目录:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 <?php namespace App \Repositories ;use App \User ;use App \Task ;class TaskRepository { public function forUser (User $user ) { return Task ::where ('user_id' , $user ->id) ->orderBy ('created_at' , 'asc' ) ->get (); } }
注入Repository
Repository创建好之后,通过在TaskController的构造函数以类型提示的方式注入该Repository,然后就可以在index方法中使用。
由于laravel使用容器来解析所有控制器,所以依赖会被自动注入到控制器:
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 <?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 { protected $tasks ; public function __construct (TaskRepository $tasks ) { $this ->middleware ('auth' ); $this ->tasks = $tasks ; } public function index (Request $request ) { return view ('tasks.index' , [ 'tasks' => $this ->tasks->forUser ($request ->user ()), ]); }
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 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 <?php namespace App \Policies ;use App \User ;use App \Task ;use Illuminate \Auth \Access \HandlesAuthorization ;class TaskPolicy { use HandlesAuthorization ; public function destroy (User $user , Task $task ) { return $user ->id === $task ->user_id; } }
最后,需要关联Task模型和TaskPolicy,通过在app/Providers/AuthServiceProvider.php的policies属性添加注册实现。
注册后会告知Laravel无论何时尝试授权到Task实例时,该使用哪个策略类进行判断:
1 2 3 protected $policies = [ 'App\Task' => 'App\Policies\TaskPolicy' , ];
授权动作
编写好策略后,在destroy方法中使用它。所有的laravel控制器都可以调用authorize方法,该方法由AuthorizesRequest提供:
app/Controllers/TaskController.php文件。
1 2 3 4 public function destroy (Request $request , Task $task ) { $this ->authorize ('destroy' , $task ); }
4.7.4 删除任务 最后在destroy方法中实际删除任务。使用Eloquent的delete方法从数据库中删除给定的模型实例。
删除后返回/tasks连接:
app/Controllers/TaskController.php文件中完整的TaskController@destroy方法。
1 2 3 4 5 public function destroy (Request $request , Task $task ) { $this ->authorize ('destroy' , $task ); $task ->delete (); return redirect ('/tasks' ); }