ここでは公式サイトの中級チュートリアルを参考に。 https://laravel.com/docs/5.1/quickstart-intermediate
認証が手早く実装出来るのはとても楽。
データベース
セットアップ
データベースを作ったら、.envの編集をして接続確認をしておく。 ※MAMPの場合は、/config/database.phpでunix_socket の調整が必要。
'unix_socket' => '/Applications/MAMP/tmp/mysql/mysql.sock',
テーブル作成
今回はUsers, Tasksが必要となる。 Usersは既にデフォルトでLaravel migrationsファイルが存在するのでそれを使う。
Tasksは下記の様にmigrationする。
php artisan make:migration create_tasks_table --create=tasks
テーブルは、以下のように定義。 CreateTasksTable.php
public function up()
{
Schema::create('tasks', function (Blueprint $table) {
$table->increments('id');
$table->integer('user_id')->index();
$table->string('name');
$table->timestamps();
});
}
編集したら、migration.
php artisan migrate
show tablesして, Tableが出来ていることを確認。
認証
Laravelでの認証は超簡単
php artisan make:auth
としたあとに、
php artisan migrate
で、必要なコントローラ・ビューが生成される。 この状態で、../register/へ行くとユーザー登録からログイン・ログアウトが可能になる。 素晴らしい。 最もシンプルな形だが、今回はこれでよしとする。
Eloquent
Eloquentとは
Eloquentとは優れていることを意味する形容詞。 LaravelのEloquent ModelsとはLaravelがデフォルトで持つ優れたORM(Object relational mapper)のこと。 ひとまずモデルとの紐つけ方のこととざっくり理解しておく。
Model作成
今回はUser, Taskの2つのModelを用意することになる。 Userはデフォルトで格納されているので、それを利用。 Taskはartisanで作ってみる。
php artisan make:model Task
これでappディレクトリに2つのファイルが生成される。
$fillableの定義
ここで $fillable を定義しておく。 $fillable とはホワイトリストのこと。 つまりユーザーが入力可能な項目を指す。 今回はnameだけかな。
Task.php
protected $fillable = ['name'];
ちなみに逆のブラックリストは、$guarded。 これらは片方のみの指定となるらしいので注意
Relationship
cakephpでいうhasmanyやhasoneのこと。 今回はUserは複数のTaskを持ち、TaskはUserに属する。
User.php
/**
* Get all of the tasks for the user.
*/
public function tasks()
{
return $this->hasMany(Task::class);
}
Task.php
/**
* Get the user that owns the task.
*/
public function user()
{
return $this->belongsTo(User::class);
}
Controller
Task管理のメソッド記述のための、taskControllerを作成する。 artisanで作成できる。
php artisan make:controller TaskController
またはこれだと、index, create, store, destory, update, editが自動でついてくる。
php artisan make:controller TaskController --resource
Taskは閲覧・編集制限を設けるので、以下を追記する。
TaskController.php
public function __construct()
{
$this->middleware('auth');
}
Routing
ルーティングの設定は、routesのweb.phpを編集する。 多分make:authをした段階で、ルートにはhomeが割り当てられていると思うので、 今回それは残し、その後ろに追記。
web.php
Route::get('/tasks', 'TaskController@index');
Route::post('/task', 'TaskController@store');
Route::delete('/task/{task}', 'TaskController@destroy');
Repositories
データベース操作をまとめるような印象。 主に拡張性を高めることが目的の気がする。
まずはapp/Repositories ディレクトリを作成 TaskRepository.phpを作成し、user情報取得のロジックを書く。
ちなみにRepositoryをartisanで作るには、こいつをインストールすれば良さそう。
https://laracasts.com/discuss/channels/tips/repoist-laravel-5-repository-generator?page=1
TaskRepository.php
<?php
namespace App\Repositories;
use App\User;
use App\Task;
class TaskRepository
{
/**
* @paramUser$user
* @return Collection
*/
public function forUser(User $user)
{
return Task::where('user_id', $user->id)
->orderBy('created_at', 'asc')
->get();
}
}
これをTaskControllerクラスのindexメソッドで、この様に利用する.
TaskController.php
public function index(Request $request)
{
return view('tasks.index', [
'tasks' => $this->tasks->forUser($request->user()),
]);
}
Policies
Policiesとは、認可ロジックをまとめたもの。 編集権限の付与などもこれにあたるようだ。
Policyの作成
php artisan make:policy TaskPolicy
/app/Policies/TaskPolicy が生成される。 ここでユーザーIDの整合性のチェックを行う。
TaskPolicy.php
public function destroy(User $user, Task $task)
{
return $user->id === $task->user_id;
}
Policyの登録
AuthServiceProviderクラスの$policiesにTaskPolicyを追加する.
AuthServiceProvider.php
protected $policies = [
'App\Model' => 'App\Policies\ModelPolicy',
Task::class => TaskPolicy::class,
];
そしてTaskControllerクラスのdestoryで認証を行う。
TaskController.php
public function destroy(Request $request, Task $task)
{
$this->authorize('destroy', $task);
// Delete The Task...
$task->delete();
return redirect('./tasks');
}
$this->authorize()でdestoryを呼び、通ったらdelete()すると。 以上で削除実装も完了。
ここまでで、TaskControllerは以下の様になる。
TaskController.php
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Task;
use App\Repositories\TaskRepository;
class TaskController extends Controller
{
/**
* The task repository instance.
*
* @var TaskRepository
*/
protected $tasks;
public function __construct(TaskRepository $tasks)
{
// Taskは閲覧・編集制限を設けるので、以下を追記
$this->middleware('auth');
$this->tasks = $tasks;
}
/**
* Display a listing of the resource.
*
* @return \Illuminate\Http\Response
*/
public function index(Request $request)
{
// RepositoriesのforUserメソッドをここで利用
return view('tasks.index', [
'tasks' => $this->tasks->forUser($request->user()),
]);
}
/**
* Store a newly created resource in storage.
*
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\Response
*/
public function store(Request $request)
{
$this->validate($request, [
'name' => 'required|max:255',
]);
$request->user()->tasks()->create([
'name' => $request->name,
]);
return redirect('/tasks');
}
/**
* Destroy the given task.
*
* @param Request $request
* @param Task $task
* @return Response
*/
public function destroy(Request $request, Task $task)
{
$this->authorize('destroy', $task);
// Delete The Task...
$task->delete();
return redirect('./tasks');
}
}
ビューの作成
Task一覧、詳細、削除が出来るビューの作成
格納場所は
/resorces/views/tasks/index.blade.php
@extends('layouts.app')
@section('content')
<!-- Current Tasks -->
@if (count($tasks) > 0)
<div class="panel-body">
<div class="panel panel-default" >
<div class="panel-heading">
Current Tasks
</div>
<div class="panel-body">
<table class="table table-striped task-table">
<!-- Table Headings -->
<thead>
<th>Task</th>
<th> </th>
</thead>
<!-- Table Body -->
<tbody>
@foreach ($tasks as $task)
<tr>
<!-- Task Name -->
<td class="table-text">
<div>{{ $task->name }}</div>
</td>
<!-- Delete Button -->
<td>
<form action="./task/{{ $task->id }}" method="POST">
{{ csrf_field() }}
{{ method_field('DELETE') }}
<button>Delete Task</button>
</form>
</td>
</tr>
@endforeach
</tbody>
</table>
</div>
</div>
</div>
@endif
<!-- Bootstrap Boilerplate... -->
<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">
</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-plus"></i> Add Task
</button>
</div>
</div>
</form>
</div>
<!-- TODO: Current Tasks -->
@endsection
エラー表示用
/resorces/views/common/errors.php
@if (count($errors) > 0)
<!-- Form Error List -->
<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