Dog APIを利用していつでも犬に癒やされよう

# はじめに
この度、ANGEL Calendarの企画に参加しております！
記事一覧は下記のOrganizationアカウントの一覧をチェックしてみてください！
[2024-ANGEL-Dojo Organization](https://qiita.com/organizations/2024-angel-dojo)

# 犬を表示させるWebアプリケーションを作ろう
疲れた時、無性に犬に癒やされたいことはありませんか？
私はあります。仕事終わりに見る犬の動画はときにビールにも勝ります。
というわけで、今回はLaravelで動画よりもお手軽に犬を接種できるWebアプリケーションを作ります！
癒やしを求めつつ簡単なAPI連携の方法を学んでいきましょう。

※この記事内ではAWSサービスは出てきません……
AWSを利用したデプロイについては長くなりそうだったので今回はカットしました。
~~またの機会に書くかもしれません。~~

# 環境構築
## 前提条件
・Linux環境（Windowsの場合はWSLインストール・Ubuntu初期設定済み）
・Docker Desktop

## Laravelプロジェクト作成
Laravelのプロジェクトを作成して必要なものをダウンロードしていきます。
ターミナルで以下のコマンドを実行します。
```shell
curl -s "https://laravel.build/dog-api" | bash
```
`dog-api`の部分はプロジェクト名になります。好きな名前に変えてください。

```shell
cd dog-api
./vendor/bin/sail up -d
```
プロジェクト内に移動して、Laravel Sailを立ち上げます。
上記を実行すると、Dockerコンテナが起動します。

プロジェクトが立ち上がったか確認しましょう。
[http://localhost](http://localhost/)にアクセスし、Laravelのページが開ければOKです。
![localhost_.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3616162/bdf6dd8c-9212-0e92-91c2-eaaa7f71610c.png)

これで環境構築が終わりました。
いよいよ開発に入っていきましょう。

# 開発
## API
今回はこちらのAPIを利用させていただきます。
https://dog.ceo/dog-api/breeds-list
サイト内では犬の写真を提供したり、犬のおやつと称した投げ銭ができます。余裕のある方はチェックしてみてください。

## 犬をランダムに表示させる機能を作る
まずは一番簡単そうな、「ボタンを押すたびにランダムな犬の画像を表示させる機能」を作っていきます。
### コントローラー
以下のコマンドを実行してコントローラーを作成します。
```shell
sail artisan make:controller DogController
```
作成したコントローラーに以下のように記述して保存します。
```php:DogController.php
<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use Illuminate\Support\Facades\Http;

class DogController extends Controller
{
    public function show()
    {
        $response = Http::get('https://dog.ceo/api/breeds/image/random');
        $dogImage = $response->json()['message'];

        return view('dog', ['dogImage' => $dogImage]);
    }

    public function newDog()
    {
        $response = Http::get('https://dog.ceo/api/breeds/image/random');
        $dogImage = $response->json()['message'];

        return response()->json(['dogImage' => $dogImage]);
    }
}

```
### ルート
続いて、ページにアクセスしたときに先程のコントローラーを実行してくれるようにルーティングします。

route\web.phpの最後に以下の記述を追加します。
```php:web.php
Route::get('/dog', [DogController::class, 'show']);
Route::get('/dog/new', [DogController::class, 'newDog']);
```
この時、忘れずに以下の記述も追加しておきましょう。
これがないとLaravelがどのファイルから読み取ればいいかわからず、エラーになってしまいます。
```php:web.php
use App\Http\Controllers\DogController;
```

web.phpは最終的に以下の状態になっていればOKです。
```php:web.php
<?php

use Illuminate\Support\Facades\Route;
use App\Http\Controllers\DogController;

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

Route::get('/dog', [DogController::class, 'show']);
Route::get('/dog/new', [DogController::class, 'newDog']);
```
### ビュー
続いて、画面描画部分を書いていきます。

resources\viewsに「dog.blade.php」というファイルを作成し、以下のように記述します。
```php:dog.blade.php
<!DOCTYPE html>
<html>
<head>
    <title>Dog Image</title>
    <script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
</head>
<body>
    <h1>かわいいわんちゃん🐕️</h1>
    <img id="dogImage" src="{{ $dogImage }}" alt="Dog Image">
    <br>
    <button id="newDogButton">🐕️🐕️🐕️</button>

    <script>
        $(document).ready(function() {
            $('#newDogButton').click(function() {
                $.ajax({
                    url: '/dog/new',
                    method: 'GET',
                    success: function(data) {
                        $('#dogImage').attr('src', data.dogImage);
                    }
                });
            });
        });
    </script>
</body>
</html>
```
これでページが完成しました！

### ページ確認
早速[http://localhost/dog](http://localhost/dog "http://localhost/dog")にアクセスしてみましょう！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3616162/336af61a-13f9-9a7f-5e42-fd9a4d2ecbaa.png)
やったー！ 無事に表示されています！

ボタンを押してみると……
![image (1).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3616162/06ff439c-48b1-d8f1-6614-163bb24caead.png)
かわいい～～！！

## 犬種を選べるようにする機能に改修
せっかくなので、よりQOLを上げるためにもう少し改良してみます。

犬種を選べるようにしましょう。
### コントローラー
DogControllerを以下のように変更します。
```php:DogController.php
<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use Illuminate\Support\Facades\Http;

class DogController extends Controller
{
    public function show()
    {
        $response = Http::get('https://dog.ceo/api/breeds/image/random');
        $dogImage = $response->json()['message'];

        $breedsResponse = Http::get('https://dog.ceo/api/breeds/list/all');
        $breeds = array_keys($breedsResponse->json()['message']);

        return view('dog', ['dogImage' => $dogImage, 'breeds' => $breeds]);
    }

    public function newDog()
    {
        $response = Http::get('https://dog.ceo/api/breeds/image/random');
        $dogImage = $response->json()['message'];

        return response()->json(['dogImage' => $dogImage]);
    }

    public function newDogByBreed($breed)
    {
        $response = Http::get("https://dog.ceo/api/breed/{$breed}/images/random");
        $dogImage = $response->json()['message'];

        return response()->json(['dogImage' => $dogImage]);
    }
}

```
newDogByBreed()を追加しました。

### ルート
続いて、web.phpに以下のRouteを追加します。
```php:web.php
Route::get('/dog/new/{breed}', [DogController::class, 'newDogByBreed']);
```

### ビュー
dog.blade.phpは以下のように変更します。
```php:dog.blade.php
<!DOCTYPE html>
<html>
<head>
    <title>Dog Image</title>
    <script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
</head>
<body>
    <h1>かわいいわんちゃん🐕️</h1>
    <select id="breedSelect">
        <option value="">Select a breed</option>
        @foreach ($breeds as $breed)
            <option value="{{ $breed }}">{{ ucfirst($breed) }}</option>
        @endforeach
    </select>
    <button id="newDogButton">🐕️🐕️🐕️</button>
    <br>
    <img id="dogImage" src="{{ $dogImage }}" alt="Dog Image">

    <script>
        $(document).ready(function() {
            $('#newDogButton').click(function() {
                var breed = $('#breedSelect').val();
                var url = breed ? '/dog/new/' + breed : '/dog/new';
                $.ajax({
                    url: url,
                    method: 'GET',
                    success: function(data) {
                        $('#dogImage').attr('src', data.dogImage);
                    }
                });
            });
        });
    </script>
</body>
</html>

```

### ページ確認
改めてlocalhost/dogにアクセスしてみます。
![image (2).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3616162/78f228c4-393d-dd68-1a71-2b1df6f16f5a.png)
セレクトボックスが表示されています。

<br>
<br>

今回は秋田犬を見てみましょう。
![image (3).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3616162/00465b1d-6468-105a-603b-b2829a6f01fc.png)
かわいい～～～～～🐕️🐕️！

ちゃんと表示されるようになりました！

## おわりに
既存のAPIを利用することで、簡単に写真を表示させる機能を作成しました。
犬を眺めて今日もお仕事を頑張りましょう🐕️🐕️🐕️