ゼロからLaravel（社員管理システムを４５分で） 2021年版

## これからLaravelを使ってみたい人へ
LaravelはPHPフレームワークとして抜群の知名度と実績があります。
MVCフレームワークの採用、Symfonyを基盤とした堅牢性、ORMの導入、Bladeテンプレートエンジンによる可読性の高いビューの実現など、便利な機能満載のフレームワークですが、何より他のPHPフレームワークに比べて群を抜いてユーザーが多いことで、つまずいた時にもQiitaなどですぐ調べられるという点が初心者にはうれしいところです。
この記事は、2020年9月にリリースされた Laravel 8 でサクッと社員管理システムを作ってみようという内容になっています。
最新のログイン認証機能のJetStreamもさりげなく使っちゃいます。

## 環境（以下のOS、並びにソフトがインストール済みの前提）
- Windows 10
- PHP実行環境 >= 7.3
- SQLite >= 3（なくても動くっちゃ動きます）
- Composer 
- node.js
- Visual Studio Code

## プロジェクトの全体像
### 1. MVCパターン
![Untitled.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/234496/d482045c-fe03-2632-0d4c-53c0dfa60b5e.png)

### 2.画面設計
![IMG_0950.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/234496/03887973-8222-c42b-0614-19a6b15a3182.jpeg)
絵をかくのは好きな方です

### 3.実装機能
<details><summary>CRUD操作</summary><div>登録、一覧表示、更新、削除
</div></details>
<details><summary>ログイン機能</summary><div>
・ログイン画面
・ログイン後の認証
・ユーザー登録
</div></details>
<details><summary>セキュリティ対策</summary><div>
「なんでセキュリティ対策しなきゃいけないの？」と思わないで！
・パスワードは暗号化（平文ダメ！）
・CSRF対策
※csrfとは攻撃手法の一つで、外部からフォームを送信します。大量のフォームを送信したり、悪意のある偽装リクエストを第三者に送らせたりします
</div></details>
<details><summary>入力チェック</summary><div>
・必須項目
・文字数制限
</div></details>
<details><summary>ログ出力機能</summary><div>
・エラーログ
・いつ、だれがどのユーザーを更新したか
</div></details>


## プロジェクトを作成
1. 適当なフォルダを作成してクリック
![Untitled 1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/234496/16ca48ed-e5a7-6c0a-f147-6828f975c7e4.png)

2. フォルダのパスが書かれているところに `cmd`  と入力して `Enter`
![Untitled 2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/234496/2954ae57-35fa-7609-4d73-b4004b9d729e.png)


3. コマンドプロンプトが開くので、以下のコマンドを実行
![Untitled 3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/234496/38a361b6-b180-dab8-66ef-b27e02d49bd5.png)

プロジェクトフォルダが作成され、何やらいろいろダウンロードされます（5分位かかるかも）
![Untitled 4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/234496/3cc3f905-4bde-2bfd-8d50-8cf4394ac6ae.png)

4. 作成されたプロジェクトフォルダを右クリックするなどして、Visual Studio Codeで開きます
![Untitled 5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/234496/1815d736-12c1-1622-420c-4fa0c443f589.png)

5. Visual Studio Codeの画面が開くので、`Ctrl + @` でターミナルを開きます
![Untitled 6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/234496/309d2415-067e-07e1-7867-abb0260bf376.png)

これで準備は完了です
以降はここのターミナルからコマンドを実行しながら開発をしていきます
![Untitled 7.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/234496/71aa32d0-a4fd-67d1-bd6d-08ea45ebccc9.png)


## プログラムの作成
### 1. アプリケーションを実行する

プロジェクトはアプリケーションに必要なファイル類を一式そろえています。Laravelに内蔵されたWebサーバー機能を使うことで、アプリケーションを実行することが出来ます。

`php artisan serve` と実行してこんな表示が出れば成功です。ローカルサーバーが立ち上がっています。
![Untitled 8.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/234496/7459d626-4f69-3f53-1bb6-99bcd3f4c362.png)

※補足ですが、Laravelでは `php artisan コマンド [引数]` というコマンドを実行することで、Laravel独自のスクリプトファイルを作成したり、サーバーを実行したりといった便利な操作ができます。   

では、localhost:8000 にアクセスしアプリの画面が開かれるか確認しましょう
![Untitled 9.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/234496/ef896466-07ee-f3bc-20af-5ffbdc1e18b7.png)


こんな画面が表示されれば、成功しています。

※ターミナル上で `Ctrl + C` でサーバを止められます 

### 2. ログイン画面の作成
以下のコマンドを順番に実行していきます。

1. `composer require laravel/jetstream`
2. `php artisan jetstream:install livewire`
3. `npm install && npm run dev`

全部終わるまで5分位かかると思います。もし最後のコマンドでエラーが出たら、node.jsが正しくインストールされていない可能性がありますので`npm`コマンドが実行できるようにしてください。

### 3.DBの設定

プロジェクトフォルダ内の`.env`ファイルを修正してDB設定をします。
![Untitled 10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/234496/f063b13f-2a48-3e96-8457-c164f7165869.png)


デフォルトでmysqlが設定されているこの６行を１行にします。
ここを↓
![Untitled 11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/234496/6fac9eda-a96c-88fd-a4b1-7ec198c02bc9.png)
こう↓
![Untitled 12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/234496/c26eaf04-b9a4-1b09-1180-8569aae79f8d.png)


そして「database」フォルダの下に`database.sqlite`という新規ファイルを作成します。
![Untitled 13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/234496/fc21693f-cb04-2485-1fe5-3a61101e4ff5.png)
![Untitled 14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/234496/2bb10742-ab4c-2376-d4b7-a0d020c208e0.png)
クライアント/サーバー型のDBに対して、SQLiteはこのようにファイルを作成するだけでOKなので楽ですね。

### 補足 Laravel のDBに対するアプローチ
DBの設定ができたら、DBのアプリの中でテーブルのカラムや型を定義して、主キーを決めて…というのがよくある手順ですが、Laravelでは通常そういうことはしません。
**マイグレーション**という機能を使い、PHPで書かれたマイグレーションファイルを用意して、テーブルの作成や修正、削除を行います。
従来のやり方がデータファーストというのに対して、この手法はコードファーストと呼ばれ、プロジェクトの途中でのテーブル構造の修正が比較的容易であることから、最近の開発の主流になりつつあります。多分。

「database」フォルダの中に「migrations」というフォルダがあります。この中に入っているのがマイグレーションファイルです。
![Untitled 15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/234496/bf0c67a8-9984-84c1-f831-792d6eeefbac.png)


一番上にある`2014_10_12_000000_create_users_table.php`というファイルを見てみましょう。
細かい意味についてここで理解する必要はありませんが、テーブル名やカラム名や型といったテーブル構造をここで定義しているのがなんとな～くわかると思います。

![Untitled 16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/234496/87f081d8-e697-82e1-1ab9-dc6adf6e2296.png)


これらのマイグレーションファイルは、まだ実際にDBの中にテーブルとして入ってはいません。
DBはまだ空の状態です。
以下のコマンドを実行することで、テーブルが作成されます。

`php artisan migrate`

エラーが出なければ成功です。
![Untitled 17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/234496/230d37a2-cb2f-07ca-5eb8-fd787884a2e5.png)



### 4. ログイン画面の確認

さて、ここで`php artisan serve` を実行して、Webアプリの状態を確認したいと思います。
![Untitled 18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/234496/ed71671b-932b-e7cf-a810-cefb4fdc634a.png)


すると画面右上に、先ほどまではなかった、「Login」「Register」というリンクが存在しているのがわかります。

入力チェックや、パスワード忘れの際のメールによるパスワード再設定、パスワード確認フィールド、複雑さの要件を満たしたパスワードのチェックといったログイン画面と登録画面に最低必要であろう機能が、既にそろった状態で追加されています。
![Untitled 19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/234496/5c2cfb9d-511b-495c-1cac-6dd829073b53.png)

適当なアカウントを作成して、登録をすると、ログインすることができます。
![Untitled 20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/234496/424ac06d-89ab-2a44-c415-31d2a223d6df.png)

「Profile」では、名前やパスワードの変更、さらには２要素認証の設定やログイン履歴の確認といったこともできるのが確認できます。
![Untitled 21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/234496/32a87c50-efc5-548f-7b68-7a4b0c60f7b8.png)

sqliteをインストールした人は、以下のコマンドを実行し、今登録したアカウントを確認してみましょう。

`cd database`  カレントディレクトリの変更
`sqlite3 database.sqlite` sqlite の実行
`select * from users;` usersテーブルの情報を取得
![Untitled 22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/234496/8f7b5fa8-eca2-1f88-0288-46eb23c278e1.png)


するとこんな画面が表示されると思います。左からID, 名前, メール, パスワード…となっていますが、注目すべきは、既にパスワードが暗号化された状態になっているということです。
特に意識をしなくてもセキュリティの面でもしっかりしたユーザーテーブルが作成されているのがわかります。
※`Ctrl + C`で抜けられます

### 5. 社員テーブルの作成

では、社員情報を設定したマイグレーションファイルを作ってみましょう。
次のコマンドを実行してください。
※ カレントディレクトリが「database」のままの人は、`cd ..` でプロジェクトフォルダにカレントディレクトリを移動してください。  

`php artisan make:migration create_employees_table --create=employees`

エラーがおきなければ「migrations」フォルダ内に新しくファイルが作成されているので、up メソッドの中に２行追加します。

```php:yyyy_MM_dd_hhmmss_create_employees_table.php
Schema::create('employees', function (Blueprint $table) {
            $table->id();
            $table->string('name');　//<--新規追加（名前）
            $table->string('skill'); //<--新規追加（保有スキル）
            $table->timestamps();
        });
```

保存し、`php artisan migrate` でテーブルを作成します。

ここから、プロジェクトの全体構成の「MVCパターン」の図に沿って、ルーティング、モデル、コントローラー、ビューを作成していきます。

### 6. ルーティングの設定
「routes」フォルダの下に`web.php` というファイルがあるので、これを修正します。
![Untitled 23.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/234496/511ad967-79e8-d857-df02-13a35aa50c80.png)


一般的なWebサイトでは、Webサーバーの公開フォルダの中にファイルを用意しておくと、そのままそのファイルにアクセスができます。
しかし、Laravelのようなフレームワークを使っている場合、そうはなりません。Laravelは、特定のアドレスにアクセスをすると、**そのアドレスに割り付けられたプログラム**が実行され、それによって必要な処理や画面表示などが作られます。
そういった機能のことをルーティングと言います。

ファイル内の以下の個所を書き換えます。

**書き換え前**

```php:web.php
Route::middleware(['auth:sanctum', 'verified'])->get('/dashboard', function () {
    return view('dashboard');
})->name('dashboard');
```

**書き換え後**

```php:web.php
Route::middleware(['auth:sanctum', 'verified'])->group(function(){
    Route::get('/dashboard',[EmployeeController::class, 'index'])->name('dashboard');

    Route::get('/employee',[EmployeeController::class, 'add']);
    Route::post('/employee',[EmployeeController::class, 'create']);
    
    Route::get('/employee/{employee}', [EmployeeController::class, 'edit']);
    Route::post('/employee/{employee}', [EmployeeController::class, 'update']);
});
```

細かいLaravelの文法については説明しませんが、あるアドレスにアクセスされたら、指定のコントローラーのメソッドを呼び出す、ということを各行で行っています。middlewareがどうこうというところは、ログイン認証済みかどうかを判断しています。

```php
Route::HTTPアクセスの種類(アドレス, 呼び出すメソッド);
```

また、以下のインポート文も追加するのを忘れないようにしてください。

```php:web.php
use App\Http\Controllers\EmployeeController; 
```

### 7. モデルの作成

次にモデルを作成します。

`php artisan make:model Employee`

以上です。今回は、モデルの修正は行いません。

### 8. コントローラーの作成

`php artisan make:controller EmployeeController`

以上です。

- コントローラーの修正

    ルーティングで設定した５つの遷移先メソッドに、処理を書き込んでいます。

    ```php:EmployeeController.php
    <?php

    namespace App\Http\Controllers;

    use Illuminate\Http\Request;
    use App\Models\Employee;
    use Illuminate\Support\Facades\Log;

    class EmployeeController extends Controller
    {
        public function index(){
            $employees = Employee::all();
            return view('dashboard', compact('employees'));
        }

        public function add(){
            return view('add');
        }

        public function create(Request $request){
            $this->validate($request, [
                'name' => 'required|min:2',
                'skill' => 'required'
            ]);

            $employee = new Employee();
            $employee->name = $request->name;
            $employee->skill = $request->skill;
            $employee->save();
            Log::info('added user '.$employee->name.' by '.auth()->user()->name);
            return redirect('dashboard');
        }

        public function edit(Employee $employee){
            return view('edit', compact('employee'));
        }

        public function update(Request $request, Employee $employee){

            if(isset($_POST['delete'])){
                $employee->delete();
                Log::info('deleted '.$employee->name.' by '.auth()->user()->name);
                return redirect('dashboard');
            }

            $employee->name = $request->name;
            $employee->skill = $request->skill;
            $employee->save();
            Log::info('updated '.$employee->name.' by '.auth()->user()->name);
            return redirect('dashboard');
        }
    }
    ```

    入力チェックのための`validate`関数、ログ出力のための`Log::info('メッセージ')` というメソッド（正確にはファサード）を使用しています。

### 9. ビューの修正・作成

Webサイトでは、画面の表示にHTML形式のファイルを作成し、それをブラウザに表示させます。PHPでWebアプリを作成した場合、HTMLファイル内にPHPのスクリプトを混在させることができますが、著しく可読性を下げます。
少し値を表示させたいだけなのに、HTMLの中に<?php echo なんらかの処理; ?>と書かなければならず、HTMLのタグ構造を崩してしまいます。

それを解決するのがLaravelに備わっている**Blade（ブレード）**というテンプレートエンジンです。テンプレートエンジンという言葉を聞くとわけわかりませんが、簡単に言うと、HTMLの中に違和感なくPHPの処理を紛れ込ませる書き方ができる仕組みのことです。

その書き方に従って、今回は以下の３ファイルの修正・追加を行います。

- `dashboard.blade.php` の修正

    ```php:dashboard.blade.php
    <x-app-layout>
        <x-slot name="header">
            <h2 class="font-semibold text-xl text-gray-800 leading-tight">
                {{ __('Dashboard') }}
            </h2>
        </x-slot>
        <table>
            <thead>
                <tr>
                    <td>名前</td>
                    <td>スキル</td>
                    <td>操作</td>
                </tr>
            </thead>
            <tbody>
                @foreach ($employees as $employee)
                <tr>
                    <td>{{$employee->name}}</td>
                    <td>{{$employee->skill}}</td>
                    <td>
                        <a href="employee/{{$employee->id}}">編集</a>
                        <form method="POST" action="employee/{{$employee->id}}">
                            <button name="delete">削除</button>
                            {{ csrf_field() }}
                        </form>
                    </td>
                </tr>
                @endforeach
            </tbody>
        </table>
        <br>
        <a href="/employee">
            社員を追加する
        </a>
    </x-app-layout>
    ```

- `add.blade.php` の追加

    ```php:add.blade.php
    <x-app-layout>
        <x-slot name="header">
            <h2 class="font-semibold text-xl text-gray-800 leading-tight">
                {{ __('Add Employee') }}
            </h2>
        </x-slot>

        <form method="POST" action="/employee">
            <label for="name">名前</label>
            <input type="text" name="name">
            <span class="text-danger">{{ $errors->first('name') }}</span>
            <br>
            <label for="skill">スキル</label>
            <textarea name="skill"></textarea>
            <span class="text-danger">{{ $errors->first('skill') }}</span>
            <br>
            <button>登録</button>
            {{csrf_field()}}
        </form>
    </x-app-layout>
    ```

- `edit.blade.php` の追加

    ```php:edit.blade.php
    <x-app-layout>
        <x-slot name="header">
            <h2 class="font-semibold text-xl text-gray-800 leading-tight">
                {{ __('Edit Employee') }}
            </h2>
        </x-slot>

        <form method="POST" action="/employee/{{$employee->id}}">
            <label for="name">名前</label>
            <input type="text" name="name" value="{{$employee->name}}">
            <br>
            <label for="skill">スキル</label>
            <textarea name="skill">{{$employee->skill}}</textarea>
            <br>
            <button>更新</button>
            {{csrf_field()}}
        </form>
    </x-app-layout>
    ```

登録画面と編集画面はほぼ同じです。違いはフォームの送信先と、選択した従業員の情報がフォーム内に埋め込まれているかどうかです。

どの画面も、フォーム内に `{{csrf_filed()}}` という関数が書かれているのにも注目です。これはCSRF対策のためにワンタイムトークンを発行するためのものです。

※csrfとは攻撃手法の一つで、外部からフォームを送信します。大量のフォームを送信したり、悪意のある偽装リクエストを第三者に送らせたりします。

# 作成されたアプリ
一覧画面
![Untitled 24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/234496/bf899e2a-959e-0910-0acc-d956dde2110e.png)

登録画面
![Untitled 25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/234496/c00c925c-4df1-a031-0ead-b65c72a6f718.png)

編集画面
![Untitled 26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/234496/f0722d0e-8eaf-45ea-9634-340e21e31c5d.png)


見た目はかなーりしょーもないですが、いくつかのコマンド操作と、たったの６つのファイルに手を加えただけで、社員管理システムを作ることができました。

## 最後におまけ
- サクッと機能を実装した後はCSSフレームワークやUIライブラリで見た目を整えることに時間を使いましょう。有名どころでいうと、とりあえずみんな使ってるbootstrap、追い風の吹いている感じのtailwind、個人的におすすめなmaterialize, Vuetifyがあります。
- VisualStudioCodeであればXDebugでのデバッグ実行が便利です。
- こんな機能あったらいいのにな～、こんな実装がしたいな～と思ったら大体調べれば方法が出てきます。この記事に落胆してもLaravelの事は嫌いにならないで。
- Webアプリのエンジニアとして頑張っていきたい人は、Laravelと並行してJavaScriptのフレームワークについても触っておいた方が良いです。両者は競合するものではなく、組み合わせて可能性を引き出すことができます。