LoginSignup
6

More than 3 years have passed since last update.

Laravelでタスクアプリを作る

Last updated at Posted at 2020-06-09

202006091556.png

下記の「Laravel 5.2 中級者向けタスクリスト」を、Laravel 7以上での作成する方法をご紹介します。ボリュームが多いので、解説は少なめです。認証機能以外はほぼ同じです。

作業環境

OS:Windows 10 HOME Edition(ver.2004)
Laravel:7.14.1
Xampp:7.4.6
Composer:1.10.7
Node.js:13.9.0

①Laravelのインストール

Composerをインストール

Laravelをインストールするには、Composerというソフトが必要です。
Composerはプログラムの依存関係を解消できるソフトで、簡単に説明するとLaravelを動かすために必要な部品をComposerがまとめて用意してくれる、便利なソフトです。
https://getcomposer.org/
上記のページにアクセスすると、下記のような画面が出てきます。
202006031927.png
「Download」を選び、ダウンロードしたファイルをダブルクリックをして、全て「Next」を選んでインストールしておきます。

Windows PowerShell(管理者)からLaravelをインストールする

PowerShellを管理者権限で実行し、以下のコマンドを打ち、Xamppのhtdocsのフォルダまで移動します。

cd C:\xampp\htdocs

次に以下のコマンドを打ち、Laravelをインストールします。

composer create-project laravel/laravel laravel_todo --prefer-dist

「laravel_todo」はフォルダ名ですので、好きなものを指定してください。
「--prefer-dist」と指定すると解凍したフォルダをダウンロードするので、インストールの時間が短くなります。

Application key set successfully.

上記の表示が出てくれば、Laravelの最新版がインストールが完了です。
また、バージョンを指定した場合は以下のように入力します。

composer create-project laravel/laravel laravel_todo --prefer-dist "6.0.*'

この場合だと、Laravelの「6.0.*」の「*」の部分の数字が一番最新のものがインストールされます。

Laravelの簡易サーバーを実行する

PowerShellで先程作ったフォルダに移動します。

cd laravel_todo

以下のコマンドを打ち、Larabelの簡易サーバーを起動します。

php artisan serve

XamppのApecheとMySQLを起動して、http://127.0.0.1:8000/ にアクセスし、下記の画面が表示されていればOKです。
202006090953.png
※簡易サーバーの実行を止めるには、PowerShellで「Ctrl」+「C」ボタンを押すと止めることができます。
※PowerShellを2つ起動し、1つで簡易サーバーを実行し、残りでコマンドを打っていくのがおすすめです。

②Laravelの初期設定

Laravelの初期設定を行います。

Laravelのタイムゾーンと言語設定

Laravelのタイムゾーンと言語設定を行います。
「config」フォルダの中の「app.php」をエディタで開き、該当箇所を下記のように変更します。

config/app.php
70行目 'timezone' => 'Asia/Tokyo',
83行目 'locale' => 'ja',

データベースの言語設定

データベースの言語設定を行います。
「config」フォルダの中の「database.php」をエディタで開き、該当箇所を下記のように変更します。

config/database.php
55行目 'charset' => 'utf8',
56行目 'collation' => 'utf8_unicode_ci',

デバックバーのインストール

デバックバーをPowerShellから下記のコマンドを実行してインストールします。

composer require barryvdh/laravel-debugbar

簡易サーバーを起動して、http://127.0.0.1:8000/ にアクセスし、下記の画面が表示されていればOKです。
202006091035.png

デバックバーを非表示するには「.env」ファイルを下記のように書き換えます。

4行目 APP_DEBUG=false

③データベースの準備

データベースの設定

xamppからphpMyAdminを起動してデータベースとユーザーを設定し、設定した情報を「.env」ファイルに書きこみます。

4行目 DB_CONNECTION=mysql
5行目 DB_HOST=127.0.0.1
6行目 DB_PORT=3306
7行目 DB_DATABASE=laravel_todo
8行目 DB_USERNAME=ユーザー名
9行目 DB_PASSWORD=パスワード

今回は「laravel_todo」というデータベース名にしました。ユーザーを設定しない場合は、Xamppの場合は下記のままでOKです。

4行目 DB_CONNECTION=mysql
5行目 DB_HOST=127.0.0.1
6行目 DB_PORT=3306
7行目 DB_DATABASE=laravel_todo
8行目 DB_USERNAME=root
9行目 DB_PASSWORD=

データベースマイグレーション

Userテーブルとtasksテーブルを作ります。
Laravelではコマンドを実行することで、テーブルを作れる仕組みになっています。
UserテーブルはLaravelのデフォルトのファイルを使用します。tasksテーブルは、PowerShellで以下のコマンドを実行して作成します。

php artisan make:migration create_tasks_table --create=tasks

「database」フォルダ→「migration」フォルダ→「2020_06_09_111346_create_tasks_table.php」を開きます。
※ファイル名は、作成した日付が先頭に入るので、違うファイル名になりますが問題ありません。
下記のように変更して保存します。

2020_06_09_111346_create_tasks_table.php
<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

class CreateTasksTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('tasks', function (Blueprint $table) {
            $table->increments('id');
            $table->integer('user_id')->unsigned()->index();
            $table->string('name');
            $table->timestamps();
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('tasks');
    }
}

これでtasksテーブルを作る準備ができたので、下記のコマンドを実行し、テーブルを作成します。

php artisan migrate

phpMyAdminを確認すると、下記のようなテーブルが作成されています。
202006091126.png

Eloquentモデル

UserモデルとTaskモデルを作成します。
今回はUserモデルはLaravelが最初から用意してものを使用するので、Taskモデルを作ります。以下のコマンドを実行します。

php artisan make:model Task

「app」フォルダに「Task.php」が作成されるので、以下のように書き換えます。

app/Task.php
<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Task extends Model
{
    /**
     * 複数代入を行う属性
     *
     * @var array
     */
    protected $fillable = ['name'];
}

Eloquentリレーション

これでModelが定義できたので、関連付けを行います。
最初にUserモデルに対するtasksリレーションを定義します。「app」フォルダに「User.php」を下記のように追記します。

app/User.php
<?php

namespace App;

use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;

class User extends Authenticatable
{
    // 他のEloquentプロパティー…

    /**
     * 特定ユーザーの全タスク取得
     */
    public function tasks()
    {
        return $this->hasMany(Task::class);
    }
}

次に、Taskモデルに対するuserリレーションを定義します。「app」フォルダに「Task.php」を下記のように追記します。

app/Task.php
<?php

namespace App;

use App\User;
use Illuminate\Database\Eloquent\Model;

class Task extends Model
{
    /**
     * 複数代入を行う属性
     *
     * @var array
     */
    protected $fillable = ['name'];

    /**
     * タスク所有ユーザーの取得
     */
    public function user()
    {
        return $this->belongsTo(User::class);
    }
}

以上でリレーションができたので、コントローラーを作成します。

④ルーティング

認証

Laravel6以降は「php artisan make:auth」というコマンドが使用できないので、公式マニュアルを参照して、以下の手順で認証機能を有効化します。
まずは、次のコマンドを実行し、laravel/uiパッケージをインストールします。

composer require laravel/ui

laravel/uiパッケージをインストールできたら、ui Artisanコマンドを使い、ログイン/ユーザー登録スカフォールドを生成します。今回はbootstrapを使用しますが、vueとreactを使用することもできます。

php artisan ui bootstrap --auth

CSSとJavaScriptをLaravelで生成するために、必要なパッケージをNodeプロジェクトマネージャー(NPM)を使用してインストールします。(Node.jsのインストールが必要です)

npm install

これで準備ができたので、以下のコマンドを実行すると、CSSとJSが生成され、ログイン機能を実装することができます。

npm run dev

実行が終わると、「node_modules」フォルダにたくさんのファルダやファイルが追加されます。例えば、http://127.0.0.1:8000/login にアクセスすると画面が表示されるようになります。

次に認証関連の機能を変更していきます。「app」フォルダ→「Http」フォルダ→「Controllers」フォルダ→「Auth」フォルダの中にある「LoginController.php」を以下のように修正します。

app/Http/Controllers/Auth/LoginController.php
29行目 protected $redirectTo = '/tasks';

同じように、「app/Http/Middleware/RedirectIfAuthenticated.php」ファイルのリダイレクトパスも変更します。

app/Http/Middleware/RedirectIfAuthenticated.php
22行目 return redirect('/tasks');

タスクコントローラー

タスクを取得したり、保存したりする必要がありますので、次のコマンドを実行し、TaskControllerを作成します。

php artisan make:controller TaskController

これでコントローラーが生成できました。続いてこのコントローラーを実行するルートを、次のコマンドを実行して作成します。

php artisan make:controller TaskController

続いて、このコントローラーを実行するルートを「routes/web.php」に以下のように変更します。

routes/web.php
<?php

use Illuminate\Support\Facades\Route;

Route::get('/', function () {
    return view('welcome');
});

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

作成された「app/Http/Controllers/TaskController.php」を以下のように記述します。

app/Http/Controllers/TaskController.php
<?php

namespace App\Http\Controllers;

use App\Http\Requests;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;

class TaskController extends Controller
{
    /**
     * 新しいコントローラインスタンスの生成
     *
     * @return void
     */
    public function __construct()
    {
        $this->middleware('auth');
    }
}

⑤レイアウトとビューの構築

子ビューの定義

TaskControllerのindexメソッドに対応する、「resources/views/tasks/index.blade.php」を作成し、以下の内容を記述します。

resources/views/tasks/index.blade.php
<!-- resources/views/tasks/index.blade.php -->

@extends('layouts.app')

@section('content')

    <!-- Bootstrapの定形コード… -->

    <div class="panel-body">
        <!-- バリデーションエラーの表示 -->
        @include('common.errors')

        <!-- 新タスクフォーム -->
        <form action="{{ url('task') }}" method="POST" class="form-horizontal">
            {{ csrf_field() }}

            <!-- タスク名 -->
            <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>

            <!-- タスク追加ボタン -->
            <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

次にTaskControllerのindexメソッドを作成し、このビューを返すようにします。

app/Http/Controllers/TaskController.php
<?php

namespace App\Http\Controllers;

use App\Http\Requests;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;

class TaskController extends Controller
{
    /**
     * 新しいコントローラインスタンスの生成
     *
     * @return void
     */
    public function __construct()
    {
        $this->middleware('auth');
    }

    /**
     * ユーザーの全タスクをリスト表示
     *
     * @param  Request  $request
     * @return Response
     */
    public function index(Request $request)
    {
        return view('tasks.index');
    }
}

⑥タスク追加

バリデーション

TaskControllerにstoreメソッドを追加します。

app/Http/Controllers/TaskController.php
/**
 * 新タスク作成
 *
 * @param  Request  $request
 * @return Response
 */
public function store(Request $request)
{
    $this->validate($request, [
        'name' => 'required|max:255',
    ]);

    // タスクの作成処理…
    $request->user()->tasks()->create([
        'name' => $request->name,
    ]);

    return redirect('/tasks');
}

$errors変数

「resources/views/common/errors.blade.php」を作成し、以下の内容を記述します。

resources/views/common/errors.blade.php
<!-- resources/views/common/errors.blade.php -->

@if (count($errors) > 0)
    <!-- フォームのエラーリスト -->
    <div class="alert alert-danger">
        <strong>おや?何かがおかしいようです!</strong>

        <br><br>

        <ul>
            @foreach ($errors->all() as $error)
                <li>{{ $error }}</li>
            @endforeach
        </ul>
    </div>
@endif

⑦既存タスク表示

既存の全タスクをビューに渡すように、TaskController@indexメソッドを編集します。

app/Http/Controllers/TaskController.php
/**
 * ユーザーの全タスクをリスト表示
 *
 * @param  Request  $request
 * @return Response
 */
public function index(Request $request)
{
    $tasks = $request->user()->tasks()->get();

    return view('tasks.index', [
        'tasks' => $tasks,
    ]);
}

依存注入

TaskRepositoryを定義します。「app/Repositories」フォルダを作成し、TaskRepositoryクラスを追加します。

app/Repositories/TaskRepository.php
<?php

namespace App\Repositories;

use App\User;

class TaskRepository
{
    /**
     * 指定ユーザーの全タスク取得
     *
     * @param  User  $user
     * @return Collection
     */
    public function forUser(User $user)
    {
        return $user->tasks()
                    ->orderBy('created_at', 'asc')
                    ->get();
    }
}

TaskControllerに下記のように編集と追記をします。

app/Http/Controllers/TaskController.php
<?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
{
    /**
     * タスクリポジトリーインスタンス
     *
     * @var TaskRepository
     */
    protected $tasks;

    /**
     * 新しいコントローラーインスタンスの生成
     *
     * @param  TaskRepository  $tasks
     * @return void
     */
    public function __construct(TaskRepository $tasks)
    {
        $this->middleware('auth');

        $this->tasks = $tasks;
    }

    /**
     * ユーザーの全タスクをリスト表示
     *
     * @param  Request  $request
     * @return Response
     */
    public function index(Request $request)
    {
        return view('tasks.index', [
            'tasks' => $this->tasks->forUser($request->user()),
        ]);
    }
}

タスク表示

タスクを表示するため、「tasks/index.blade.php」に以下のように追記をします。

tasks/index.blade.php
@extends('layouts.app')

@section('content')
    <!-- タスクフォームの作成… -->

    <!-- 現在のタスク -->
    @if (count($tasks) > 0)
        <div class="panel panel-default">
            <div class="panel-heading">
                Current Tasks
            </div>

            <div class="panel-body">
                <table class="table table-striped task-table">

                    <!-- テーブルヘッダ -->
                    <thead>
                        <th>Task</th>
                        <th>&nbsp;</th>
                    </thead>

                    <!-- テーブル本体 -->
                    <tbody>
                        @foreach ($tasks as $task)
                            <tr>
                                <!-- タスク名 -->
                                <td class="table-text">
                                    <div>{{ $task->name }}</div>
                                </td>

                                <td>
                                    <!-- TODO: 削除ボタン -->
                                </td>
                            </tr>
                        @endforeach
                    </tbody>
                </table>
            </div>
        </div>
    @endif
@endsection

⑧タスク削除

削除ボタンの追加

「tasks/index.blade.php」に以下を追記

tasks/index.blade.php
<tr>
    <!-- タスク名 -->
    <td class="table-text">
        <div>{{ $task->name }}</div>
    </td>

    <!-- 削除ボタン -->
    <td>
        <form action="{{ url('task/'.$task->id) }}" method="POST">
            {{ csrf_field() }}
            {{ method_field('DELETE') }}

            <button type="submit" id="delete-task-{{ $task->id }}" class="btn btn-danger">
                <i class="fa fa-btn fa-trash"></i>削除
            </button>
        </form>
    </td>
</tr>

ポリシーを作る

PowerShellで以下のコマンドを実行して、TaskPolicyを作成します。

php artisan make:policy TaskPolicy

作成された「app/Policies/TaskPolicy.php」を以下のように編集します。

app/Policies/TaskPolicy.php
<?php

namespace App\Policies;

use App\User;
use App\Task;
use Illuminate\Auth\Access\HandlesAuthorization;

class TaskPolicy
{
    use HandlesAuthorization;

    /**
     * 指定されたユーザーが指定されたタスクを削除できるか決定
     *
     * @param  User  $user
     * @param  Task  $task
     * @return bool
     */
    public function destroy(User $user, Task $task)
    {
        return $user->id === $task->user_id;
    }
}

最後に「app/Providers/AuthServiceProvider.php」ファイルの$policiesプロパティに一行加えることで、TaskモデルをTaskPolicyと関連付けします。

app/Providers/AuthServiceProvider.php
<?php

namespace App\Providers;

use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider;
use Illuminate\Support\Facades\Gate;

class AuthServiceProvider extends ServiceProvider
{
    /**
     * アプリケーションにマップするポリシー
     *
     * @var array
     */
    protected $policies = [
      'App\Task' => 'App\Policies\TaskPolicy',
    ];

    /**
     * Register any authentication / authorization services.
     *
     * @return void
     */
    public function boot()
    {
        $this->registerPolicies();

        //
    }
}

タスク削除

タスクを削除する機能をTaskControllerに記述します。

app/Http/Controllers/TaskController.php
/**
 * 指定タスクの削除
 *
 * @param  Request  $request
 * @param  Task  $task
 * @return Response
 */
public function destroy(Request $request, Task $task)
{
    $this->authorize('destroy', $task);

    $task->delete();

    return redirect('/tasks');
}

見た目を整える

5年前のチュートリアルでBootstrapの記述が古いので、お好みで変更を適宜加えます。

202006092052.png

以上で完成です。お疲れさまでした。

参考ページ

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
6