LoginSignup
3
1

More than 5 years have passed since last update.

Laravel 中級Task Listの5.4バージョン

Last updated at Posted at 2018-09-26

Laravel Practice

Laravelをざっと理解するため、公式サイトの中級TaskListをやってみたのでそのログです。
https://laravel.com/docs/5.1/quickstart-intermediate

基本的なCRUDと、ログイン機能がついたものです。
なお上記URLはこれは5.1なので、5.4に合わせて各所調整しています。

github
https://github.com/shnr/laravel_tasklist

Laravel Version
Laravel Framework 5.4.36

インストール

composer install

https://getcomposer.org/download/

チュートリアルままですが、まずはプロジェクトディレクトリを作って、composerのダウンロード。

$ mkdir myproject-dir
$ cd myproject-dir
$ php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');"
$ php -r "if (hash_file('SHA384', 'composer-setup.php') === '544e09ee996cdf60ece3804abc52599c22b1f40f4323403c44d44fdfdd586475ca9813a858088ffbc1f233e9b180f061') { echo 'Installer verified'; } else { echo 'Installer corrupt'; unlink('composer-setup.php'); } echo PHP_EOL;"
$ php composer-setup.php
$ php -r "unlink('composer-setup.php');"

そしてlaravel install.

$ php composer.phar create-project --prefer-dist laravel/laravel mytasklist

インストールの確認

$ cd mytasklist/
$ php artisan --version
Laravel Framework 5.4.36

データベース

セットアップ

データベースを作ったら、.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情報取得のロジックを書く。

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>&nbsp;</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
3
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
1