Laravel Task List

Laravel Practice

Laravelをざっと理解するために、公式サイトの中級TaskListを読んでみました。
https://laravel.com/docs/5.1/quickstart-intermediate

基本的なCRUDに、ログイン機能がついたものです。
なおこのチュートリアルは5.1だったので、5.4に合わせて各所調整しています。

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

目標とする仕様
ユーザ管理の実装
各ユーザーごとのタスクの閲覧が可能

サーバ仕様
PHP 7.2
mysql 5.7

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。
mytasklistというディレクトリ名としました。

$ 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だけでOKです。

Task.php

protected $fillable = ['name'];

ちなみに逆のブラックリストは、$guarded。
これらは片方のみの指定となるらしいので注意

Relationship

cakephpでいうhasmanyやhasoneのことですね。
今回はUserとTaskは1対多の関係になります。

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を編集します。
※api向けにapi.phpがあります。
多分make:authをした段階で、ルートにはhomeが割り当てられていると思うので、
今回それは残し、その後ろに追記します。

web.php

Route::get('/tasks', 'TaskController@index');
Route::post('/task', 'TaskController@store');
Route::delete('/task/{task}', 'TaskController@destroy');

Repositories

Repositoryとは、データベース操作をまとめておき、拡張性を高めることが目的、と理解しています。
また、アクション内でコントローラのオブジェクトにアクセスしやすくなるため、ソース見通しもよくなりそうです。

まずはapp/Repositories ディレクトリを作成します。
TaskRepository.phpを作成し、user情報取得のロジックを書きます。

TaskRepository.php

<?php
namespace App\Repositories;
use App\User;
use App\Task;

class TaskRepository
{
    /**
     * @param  User  $user
     * @return Collection
     */
    public function forUser(User $user)
    {
        return Task::where('user_id', $user->id)
                    ->orderBy('created_at', 'asc')
                    ->get();
    }
}

これをTaskControllerクラスのindexメソッドで、この様に利用します。

    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の整合性のチェックを行い、boolで返します。

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でこれを利用できます。
$this->authorize(‘destroy’, $task);
のところです。

    public function destroy(Request $request, Task $task)
    {
        $this->authorize('destroy', $task);

        // Delete The Task...
        $task->delete();

        return redirect('./tasks');

    }

$this->authorize()でdestoryを呼び、通ったらdelete()するということになります。

以上で、追加・閲覧・削除が可能となりました。