Laravelで作成したAPIをReactで利用する

Laravel で作成した API でデータを取得し、React で表示する手順をご紹介いたします。

# Laravel で API を作成する

## モデルの作成
データ取得用テーブルとして、下記カラムで `todos テーブル` を作成しておきます。

| id | title | created_at | updated_at |
|---|---|---|---|

次に todos テーブルを扱えるよう、 `Todo モデル` を作成します。

```
php artisan make:model Todo
```

下記内容の `Todo.php` が作成されます。

```Todo.php
<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Todo extends Model
{
}
```

## API リソースの作成
React でデータを処理するので、データベースから取得したデータは JSON 形式でデータを返すようにしましょう。
今回は Laravel の API リソースを利用します。

```
php artisan make:resource TodoResource
```
コマンドを実行すると、リソースファイル（app/Http/Resources/TodoResource.php）が作成されます。

```TodoResource.php
<?php

namespace App\Http\Resources;

use Illuminate\Http\Resources\Json\JsonResource;

class TodoResource extends JsonResource
{
    /**
     * Transform the resource into an array.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return array
     */
    public function toArray($request)
    {
        return parent::toArray($request);
    }
}
```

この `TodoResource.php` を書き換え、任意の内容を JSON 形式で返却させるようにします。
今回は todos テーブルにある id, title, updated_at の内容を JSON で返却させたいので、
`toArray()` 関数の内容を下記の通りに書き換えます。

```TodoResource.php
    public function toArray($request)
    {
        return [
            'id' => $this->id,
            'title' => $this->title,
            'updated_at' => $this->updated_at->format('Y/m/d')
        ];
    }
```

updated_at の内容は format で「Y/m/d」形式に変換しています。

## コントローラの作成

作成した `TodoResource.php` を使用するためのコントローラを作成します。

```
php artisan make:controller TodoController
```

コマンドを実行すると、コントローラファイル（app/Http/Controllers/TodoController.php）が作成されます。

```TodoController.php
<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;

class TodoController extends Controller
{

}
```

このファイルに、リソースを呼び出す関数 `getTodos()` を作成します。
`use` 部分も忘れずに追加してください。

```TodoController.php
<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use App\Http\Resources\TodoResource;
use App\Todo;

class TodoController extends Controller
{
    public function getTodos()
    {
        return TodoResource::collection(Todo::all());
    }
}
```

`Todo::all()`
で todos テーブルから全ての内容を取得し、
`TodoResource::collection`
で取得内容を `TodoResource.php` に記述した内容通り（`toArray()` 部分）に JSON 形式に変換しています。

## ルーティングの設定

作成した `TodoController.php` を API として呼び出せるようにするため、
route/api.php に下記の記述を追加します。

```api.php
Route::group( ['middleware' => 'api'], function(){
    Route::get('gettodos', 'TodoController@getTodos');
});
```

これで `/api/gettodos` にアクセスすると、todos テーブルの内容を全て格納した JSON データを取得できるようになります。

<img width="689" alt="スクリーンショット 2020-04-28 12.19.39.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/608050/e34dc956-4343-7eab-d35e-353fc0599be9.png">

JSON データの中身ですが、 `TodoResource.php` で

```
return [
    'id' => $this->id,
    'title' => $this->title,
    'updated_at' => $this->updated_at->format('Y/m/d')
];
```
と記述したので、それぞれのキーには下記内容が格納されています。

| キー | 内容 |
|:--|---|
| id | todos テーブルの id |
| title | todos テーブルの title |
| updated_at | todos テーブルの updated_at（Y/m/d 形式） |

# React から API を呼び出す

## axios で データを取得する

Laravel 部分の作成は完了したので、React によるデータの呼び出し・表示部分を作成します。

まず /resources/js/components/ に `TodoApp.js` を作成します。
次に `axios` と `useEffect` で Laravel の API からデータを取得する処理を記述します。

```TodoApp.js
import React, {useState, useEffect} from 'react';
import ReactDOM from 'react-dom';

function TodoApp()
{
    const [todos, setTodos] = useState([]);

    useEffect(
        () => {
            axios
                .get( '/api/gettodos' )
                .then( (res) => {
                    setTodos(res.data.data);
                })
                .catch( (e) => {
                    console.log(e);
                })
        },
        []
    );
}

ReactDOM.render(
    <TodoApp />,
    document.getElementById('todoApp')
)
```

作成した API を呼び出すパス（/api/gettodos）を `axios` で呼び出し、JSON データを取得します。
そして `SetTodos` で `todos` 変数に全て保存する処理となっています。

## 取得したデータを表示する

`todos` に保存されているデータを `map()` でループし、表示します。
`TodoApp.js` の `TodoApp()` に下記内容を追記してください。

```TodoApp.js
    return (
        <>
        {
            todos.map( (todo) => {
                return (
                    <div key={todo.id}>
                        {todo.title} {todo.updated_at}
                    </div>
                );
            })
        }
        </>
    )
```

これで呼び出し処理は完成です。
実行すると、下記画面が表示されます。

<img width="333" alt="スクリーンショット 2020-04-28 12.38.31.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/608050/6cfb7189-f0c4-e015-de44-370ffd365c5f.png">

以上になります。

リソースを利用しない方法もありますが、リソースを利用するとすっきりと記述できます。