Laravelでアニメ一覧を取得する

# はじめに

こんにちは、エンジニアのkeitaMaxです。

https://qiita.com/keitaMax/items/3645ad9169aea6cf2d64

以前記事にした`アニメ一覧APIでアニメ情報を取得をする`の続きです。

今回はLaravel11を使用してAPIから2024年の春にやったアニメ一覧をDBに保存しようと思います。


# テーブル作成

以下コマンドでマイグレーションファイルを作成します。

```
php artisan make:migration create_animations_table
```

中身は以下のようにしました。

```php:
<?php

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

return new class extends Migration
{
    /**
     * Run the migrations.
     */
    public function up(): void
    {
        Schema::create('animations', function (Blueprint $table) {
            $table->id();
            $table->timestamps();
            $table->softDeletes();

            $table->text('title')->nullable();
            $table->text('title_kana')->nullable();
            $table->text('title_en')->nullable();
            $table->text('media')->nullable();
            $table->text('official_site_url')->nullable();
            $table->text('wikipedia_url')->nullable();
            $table->text('facebook_image_url')->nullable();
            $table->integer('episodes_count')->nullable();
            $table->text('season_name')->nullable();
        });
    }

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

```

これで以下コマンドでマイグレーションファイルを流し、テーブルを作成します。


# コマンド作成

以下のコマンドでコマンドを作成します。

```
php artisan make:command GetThisTermAnimations
```

# コマンドからAPIを叩いてDBに保存する処理を作成

以下のコマンドでコマンドを作成します。

```
php artisan make:command GetThisTermAnimations
```

# コマンドでAPIを叩く処理を作成

以下のように作成しました。

```php:GetThisTermAnimations.php
<?php

namespace App\Console\Commands;

use App\Models\Animation;
use Illuminate\Console\Command;

class GetThisTermAnimations extends Command
{
    /**
     * The name and signature of the console command.
     *
     * @var string
     */
    protected $signature = 'app:get-this-term-animations';

    /**
     * The console command description.
     *
     * @var string
     */
    protected $description = 'Command description';

    /**
     * Execute the console command.
     */
    public function handle($page = 1)
    {
        $terms = $this->argument('term');
        $termId = $this->argument('termId');
        $url = "https://api.annict.com/v1/works?filter_season=2024-spring&page=$page";
        $ch = curl_init();
        $apiKey = config('app.annict_api_key');
        $headers = [
            'Authorization: Bearer ' . $apiKey,
            'Accept: application/json',
        ];
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_FAILONERROR, true);
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
        $response = curl_exec($ch);
        $error = curl_error($ch);
        if ($error) {
            $this->info("error $error");
            return;
        }
        curl_close($ch);

        $responseArray = json_decode($response);
        foreach ($responseArray->works as $animation) {
            Animation::firstOrCreate([
                "title" => $animation->title,
                "title_kana" => $animation->title_kana,
                "title_en" => $animation->title_en,
                "media" => $animation->media,
                "official_site_url" => $animation->official_site_url,
                "wikipedia_url" => $animation->wikipedia_url,
                "facebook_image_url" => $animation->images->facebook->og_image_url,
                "episodes_count" => $animation->episodes_count,
                "season_name" => $animation->season_name,
            ]);
        }

        if ($responseArray->next_page) {
            $this->handle($responseArray->next_page);
        }
    }
}

```

１回APIを叩くと、最大25までしか取得ができないので、

```php
if ($responseArray->next_page) {
  sleep(1);
  $this->handle($responseArray->next_page);
}
```

このように次のページがあった場合にもう一度APIを叩くようにしています。

また、`sleep(1);`によって連続で叩かないようにしています。

また、`config`にAPIKeyを設定し、envファイルにキーを置いています。

# 実行

以下コマンドで実行します。

```
php artisan app:get-this-term-animations
```

これを実行し、DBを見ると実際にアニメの一覧が入っていることがわかります。

# おわりに

この記事での質問や、間違っている、もっといい方法があるといったご意見などありましたらご指摘していただけると幸いです。

最後まで読んでいただきありがとうございました！

# 参考

https://qiita.com/keitaMax/items/3645ad9169aea6cf2d64

# 次の記事