Vue.js + LaravelでシンプルなSPA構築チュートリアル：LaravelAPI編

# はじめに
Vue.jsとLaravelによるSPA実装のチュートリアル記事です。

本記事は、４本の連載記事の３本目です。

[Vue.js + LaravelでシンプルなSPA構築チュートリアル：概要編](https://qiita.com/minato-naka/items/2d2def4d66ec88dc3ca2)
[Vue.js + LaravelでシンプルなSPA構築チュートリアル：Vueフロントエンド編](https://qiita.com/minato-naka/items/9241d9c7a7433985056d)
[Vue.js + LaravelでシンプルなSPA構築チュートリアル：LaravelAPI編](https://qiita.com/minato-naka/items/0e709cb0e6628c82c1c5)
↑↑今ここ↑↑
[Vue.js + LaravelでシンプルなSPA構築チュートリアル：VueとAPI結合編](https://qiita.com/minato-naka/items/9362ea5af5f823c95b0b)



# 前回まで
前回は、Vue.jsでフロントエンドのみ実装し、
静的なSPAができました。

べた書きのサンプルデータが表示されている状態で、
・タスク一覧
・タスク詳細
・タスク登録
・タスク編集
のページが完成しています。


# API実装の進め方

この全体図の緑色部分にある
５つのAPIを実装していきます。

![Untitled Diagram.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/297693/079b7519-439b-aa1e-7fa6-e8a7ee032111.png)


今回は一番シンプルな形で進めるので、
各APIの処理は全てコントローラ内で数行で完結します。


また、API自体の実装の前に
DBのセットアップや最低限のテストデータも準備します。


# SQLiteのセットアップ
今回は作業簡略化のため
MySQLやPostgreSQLを用意せず
SQLiteを使います。

まずはSQLiteのストレージとなるファイルを用意します。

`database/database.sqlite` に空のファイルを作成すればOKです。


次に、.envのDB接続情報を修正します。

```diff:.env

- DB_CONNECTION=mysql
- DB_HOST=127.0.0.1
- DB_PORT=3306
- DB_DATABASE=laravel
- DB_USERNAME=root
- DB_PASSWORD=


+ DB_CONNECTION=sqlite

```

これでSQLiteを利用するための設定は完了です。

ただし、PHPのSQLiteドライバーが有効になっている必要がありますので
もしなっていなければ有効にしてください。
https://awesome-linus.com/2019/05/24/php-sqlite-driver-install/


# migration作成
migrationでタスクテーブルを作成します。

まずは下記コマンドでmigrationファイルを生成。

```shell
php artisan make:migration create_tasks_table
```

生成されたmigrationのupメソッドの中をこのように書き換えます。

```create_tasks_table.php
Schema::create('tasks', function (Blueprint $table) {
    $table->bigIncrements('id');
    $table->string('title', 100);
    $table->string('content', 100);
    $table->string('person_in_charge', 100);
    $table->timestamps();
});
```

commit：[migration作成](https://github.com/MinatoNaka/VueLaravelSpa/commit/c2145cbda2aa572571c0f7e8b7706735628e25ab)

# モデル作成
次に、タスクテーブルに対応する
タスクモデルを作ります。


```shell
php artisan make:model Task
```


生成されたモデルファイルに、
`$fillable` のみ追記しておきます。

```diff:app/Task.php
  class Task extends Model
  {
+    protected $fillable = [
+        'title',
+        'content',
+        'person_in_charge',
+    ];
  }
```

commit：[タスクモデル作成](https://github.com/MinatoNaka/VueLaravelSpa/commit/495e1ea59c5bf0ed6798902f551ec70d3910b85b)


# seeder作成
次に、テストデータを自動生成するための
seederを作成します。

まずは下記コマンドでseederファイルを生成。


```shell
php artisan make:seeder TasksTableSeeder
```

生成されたseederファイルのrunメソッドを
このように修正します。


```diff:database/seeds/TasksTableSeeder.php
+ use App\Task;
  use Illuminate\Database\Seeder;

  class TasksTableSeeder extends Seeder
  {
      public function run()
      {
+         for ($i = 1; $i <= 10; $i++) {
+             Task::create([
+                 'title' => 'title' . $i,
+                 'content' => 'content' . $i,
+                 'person_in_charge' => 'person_in_charge' . $i,
+             ]);
+         }
      }
  }
````


また、このseederを実行するためにDatabaseSeederファイルも修正します。

```diff:database/seeds/DatabaseSeeder.php
 public function run()
 {
-    // $this->call(UsersTableSeeder::class);
+    $this->call(TasksTableSeeder::class);
 }
```

commit：[タスクseeder作成](https://github.com/MinatoNaka/VueLaravelSpa/commit/51e43dbda8935c74e8bd52cba238649cd85268b5)

# テーブル、テストデータ生成
テーブルとテストデータを生成する準備は整いましたので、
実際に生成しましょう。

```shell
php artisan migrate --seed
```

これで先ほど作成したmigrationとseederが実行され、
テーブルとテストデータが10件できてるはずです。

データがちゃんと入っているか確認した場合は
tinkerを使ってみてください。


```shell
$ php artisan tinker


>>> Task::all();
```

これでタスクテーブルのデータが一覧で表示されます。


# タスク一覧取得API実装
それでは早速API実装を始めます。
まずはタスク一覧取得APIから。


ルーティングを追加。

```diff:routes/api.php
+ Route::get('/tasks', 'TaskController@index');
```

※
[こちらのコメント](https://qiita.com/minato-naka/items/0e709cb0e6628c82c1c5#comment-91dcb2295f6e3f0a20b5)にて、
Laravel8ではこの書き方ではうまくいかないという報告がありました。
エラーが出た場合はコメントを参考に、修正してみてください。


次に、タスクコントローラを作成し、
そこにindexメソッドを追加します。

まずはartisanコマンドでコントローラファイル自体を生成。

```shell
php artisan make:controller TaskController
```

そして、indexメソッド追加。

```diff:app/Http/Controllers/TaskController.php
+ <?php
+
+ namespace App\Http\Controllers;
+
+ use App\Task;
+
+ class TaskController extends Controller
+ {
+     public function index()
+     {
+         return Task::all();
+     }
+ }
```

ただTaskモデルから全件取得してreturnするだけです。

POSTMANなどで
http://localhost:8000/api/tasks
にリクエストすると
タスク一覧が取得できると思います。
※`routes/api.php`にルーティング定義すると、自動でパスの頭に`/api`がつきます。


レスポンスはこのようなjson形式になります。

```json:レスポンス形式
[
    {
        "id": 1,
        "title": "title1",
        "content": "content1",
        "person_in_charge": "person_in_charge1",
        "created_at": "2019-12-17 00:43:38",
        "updated_at": "2019-12-17 00:43:38"
    },
    {
        "id": 2,
        "title": "title2",
        "content": "content2",
        "person_in_charge": "person_in_charge2",
        "created_at": "2019-12-17 00:43:38",
        "updated_at": "2019-12-17 00:43:38"
    },
]
```

commit：[タスク一覧取得API実装](https://github.com/MinatoNaka/VueLaravelSpa/commit/73fff629bd1391dd6a063e9d99af7a0c1ad92440)

# タスク詳細取得API実装
次にタスク詳細取得APIです。

ルーティング追加。

```diff:routes/api.php
  Route::get('/tasks', 'TaskController@index');
+ Route::get('/tasks/{task}', 'TaskController@show');
```

コントローラにshowメソッドを追加。

```diff:app/Http/Controllers/TaskController.php
+ public function show(Task $task)
+ {
+     return $task;
+ }
```

URLパラメータで受け取ったタスクモデルを
そのままreturnするだけです。
※これでLaravelが勝手にjson形式のレスポンスを返却します


commit：[タスク詳細取得API実装](https://github.com/MinatoNaka/VueLaravelSpa/commit/4cf599a4cea3863a7b1e7fb7efe80eeb31d88c88)


# タスク登録API実装
次に、タスク登録APIです。

ルーティング追加。

```diff:routes/api.php
  Route::get('/tasks', 'TaskController@index');
+ Route::post('/tasks', 'TaskController@store');
  Route::get('/tasks/{task}', 'TaskController@show');
```

※ルーティングの定義順を間違えると正しく動かないので、この通りに記述してください


コントローラにstoreメソッド追加。

```diff:app/Http/Controllers/TaskController.php
  use App\Task;
+ use Illuminate\Http\Request;


+ public function store(Request $request)
+ {
+     return Task::create($request->all());
+ }
```

リクエストで受け取ったデータをそのまま
モデルのcreateでデータ登録しているだけです。


このようなjson形式のデータを受け取ることを想定しています。


```json:リクエスト形式
{
    "title": "new title",
    "content": "new content",
    "person_in_charge": "new person_in_charge1"
}
```


commit：[タスク登録API実装](https://github.com/MinatoNaka/VueLaravelSpa/commit/21eb78bb4ef6df05d581ed690c108b638d1f80ed)


# タスク更新API実装
次に、タスク更新APIです。

ルーティング追加。

```diff:routes/api.php
  Route::get('/tasks', 'TaskController@index');
  Route::post('/tasks', 'TaskController@store');
  Route::get('/tasks/{task}', 'TaskController@show');
+ Route::put('/tasks/{task}', 'TaskController@update');
```


コントローラにupdateメソッド追加。

```diff:app/Http/Controllers/TaskController.php
+ public function update(Request $request, Task $task)
+ {
+     $task->update($request->all());
+
+     return $task;
+ }
```

受け取るリクエストの形は、
登録APIと同じjson形式です。

URLパラメータで受け取ったTaskモデルのupdateメソッドで
そのままデータを更新するだけです。


commit：[タスク更新API実装](https://github.com/MinatoNaka/VueLaravelSpa/commit/e9f9d5318326780a95da893f671c05856f628aab)


# タスク削除API実装
次はタスク削除API。

ルーティング追加。

```diff:routes/api.php
  Route::get('/tasks/{task}', 'TaskController@show');
  Route::put('/tasks/{task}', 'TaskController@update');
+ Route::delete('/tasks/{task}', 'TaskController@destroy');
```

コントローラにdestroyメソッド追加。

```diff:app/Http/Controllers/TaskController.php
+ public function destroy(Task $task)
+ {
+     $task->delete();
+ 
+     return $task;
+ }
```

URLパラメータでTaskを受け取り、
それをそのままdeleteします。


commit：[タスク削除API実装](https://github.com/MinatoNaka/VueLaravelSpa/commit/9c97486a08bb6b42be6b9cfd7c1de5adc4e977e9)


# おわりに
これで今回必要なAPIはすべて実装完了です。

POSTMANなどを利用して、
各APIの動作を確認するといいと思います。

本来は、このAPIでは
バリデーションを入れたり、
検索処理を入れたりすることになるかと思います。


次回は、
フロントのVueからAjaxで
このAPIに対してリクエスト送信し、
実際にデータの表示、更新、登録、削除ができるようにします。
（次に進む前に、LGTMしてもらえるとうれしいです）
[Vue.js + LaravelでシンプルなSPA構築チュートリアル：VueとAPI結合編](https://qiita.com/minato-naka/items/9362ea5af5f823c95b0b)