LaravelでS3ではなくCloudflare R2を使う

## Cloudflare R2とは
https://www.cloudflare.com/ja-jp/products/r2/

### 料金設定
無料枠は以下のようになっています。
![スクリーンショット 2023-03-16 21.09.16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223280/7a034917-b675-21f9-ef2d-1bc7c223ecda.png)


## 設定の流れ
### パケットを作成する
ダッシュボードを開いたら「パケットを作成する」ボタンをクリックします
![スクリーンショット 2023-03-13 11.45.03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223280/e76141a4-19f0-71a2-d7ca-4f49f0b08f20.png)

次にパケット名を入力します。
今回は「test」で作成します。
![スクリーンショット 2023-03-13 11.48.27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223280/9f02bf04-91d1-8b87-000c-04727007c827.png)
#### パケットの情報を確認する
するとこんな感じでパケットが作成されます。
`https://〇〇.r2.cloudflarestorage.com/test`
![スクリーンショット 2023-03-13 11.50.21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223280/df4359fa-4023-c576-d828-68d5fe24187a.png)

#### `.env` に追加する
このURL情報をLaravelの `.env` に追加します
```:.env
CLOUDFLARE_R2_BUCKET=test
CLOUDFLARE_R2_ENDPOINT=https://〇〇.r2.cloudflarestorage.com
```

### APIトークンを作成する
次に LaravelからアップロードできるようにAPIの設定を行います。
#### R2 APIトークンの管理
R２のページに戻り、「R2 APIトークンの管理」をクリックします
![スクリーンショット 2023-03-13 12.20.30.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223280/7840b035-c6f3-20e9-b02f-69f660d7674c.png)

#### APIトークンを作成する
続けて「APIトークンを作成する」をクリックします
![スクリーンショット 2023-03-13 12.22.01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223280/0e645b08-3ad1-24b6-8250-fbeb0aa2305c.png)

#### アクセス許可
アクセス許可は「編集」を選択しAPIトークンを作成します
![スクリーンショット 2023-03-13 12.26.24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223280/25125179-8169-a58f-53bf-69e808ffa23e.png)

#### `.env` に追加する
APIが作成されました
![スクリーンショット 2023-03-13 12.29.58.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223280/74419845-a738-1907-f6cd-f0a66ee02d74.png)

「アクセス キー ID」、「シークレット アクセス キー」をLaravelの `.env` に追加します
```:.env
CLOUDFLARE_R2_BUCKET=test
CLOUDFLARE_R2_ENDPOINT=https://〇〇.r2.cloudflarestorage.com

// 今回追加
CLOUDFLARE_R2_ACCESS_KEY_ID=◎◎
CLOUDFLARE_R2_SECRET_ACCESS_KEY=◉◉
```

これでLaravelのAPIからデータをアップロードできるようになりました。
s3 APIと互換性があるのでアップロードは以下のような感じでできます

```:〇〇Controller.php
use Illuminate\Support\Facades\Storage;
class 〇〇Controller extends Controller
{
    Storage::disk('r2')->put('example.txt', 'Hello World');
}
```

### カスタムドメインを設定する
ここまでで、作成したtestパケットにLaravelのAPIを使ってデータをアップロードできるようになっていると思います。しかし、このままだと画像の参照ができません。
`Invalid Argument: Authorization` みたいなエラーがでるはずです。

なのでパケットにアクセスできるカスタムドメインを設定する必要があります

#### パケットの設定を開く
パケットのページを開いたら「設定」をクリックします
![スクリーンショット 2023-03-13 12.40.36.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223280/0529e859-316f-e50c-7d03-e031743c1a3e.png)

#### パブリックアクセスでドメイン接続
パブリックアクセスという項目があります。
カスタムドメインの「ドメインに接続」をクリックします
![スクリーンショット 2023-03-13 12.42.22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223280/33c4ff81-cc07-f65d-a39b-d388435bc418.png)

今回は「media.example.com」という名前でカスタムドメインを追加する想定でいきます
ドメインは取得済のものである必要があります
![スクリーンショット 2023-03-13 12.47.48.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223280/4d6fecb5-6547-0727-a417-dc8f330ef650.png)

無事に作成できると以下のようにアクティブになります
![スクリーンショット 2023-03-13 12.50.22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223280/e6a92758-92bc-5137-fbdc-9ccded6904a9.png)

#### `.env` に追加する
このドメインを `.env` に追加します。
```:.env
CLOUDFLARE_R2_ACCESS_KEY_ID=◎◎
CLOUDFLARE_R2_SECRET_ACCESS_KEY=◉◉
CLOUDFLARE_R2_BUCKET=test
CLOUDFLARE_R2_ENDPOINT=https://〇〇.r2.cloudflarestorage.com

// 今回追加
CLOUDFLARE_R2_URL=https://media.example.com
```

これでカスタムドメインを通してパケットのデータを表示することができるようになりました。
DBに保存するときはこんな感じになると思います
```:〇〇Controller.php
use Illuminate\Support\Facades\Storage;
class 〇〇Controller extends Controller
{
    Storage::disk('r2')->put('example.txt', 'Hello World');
    $text = env('CLOUDFLARE_R2_URL') . '/' . 'example.txt';
}
```

Bladeで表示するとき
```:〇〇.blade.php
{{ $text }}
```

## 最終的なLaravelの設定ファイル
- .env
```:.env
CLOUDFLARE_R2_ACCESS_KEY_ID=◎◎
CLOUDFLARE_R2_SECRET_ACCESS_KEY=◉◉
CLOUDFLARE_R2_BUCKET=test
CLOUDFLARE_R2_ENDPOINT=https://〇〇.r2.cloudflarestorage.com
CLOUDFLARE_R2_URL=https://media.example.com
```
- config/filesystems.php

`region` を `us-east-1` にしないとエラーに
```:.php
'r2' => [
    'driver' => 's3',
    'key' => env('CLOUDFLARE_R2_ACCESS_KEY_ID'),
    'secret' => env('CLOUDFLARE_R2_SECRET_ACCESS_KEY'),
    'region' => 'us-east-1',
    'bucket' => env('CLOUDFLARE_R2_BUCKET'),
    'endpoint' => env('CLOUDFLARE_R2_ENDPOINT'),
],
```
- 〇〇Controller.php
```:〇〇Controller.php
use Illuminate\Support\Facades\Storage;
class 〇〇Controller extends Controller
{
    Storage::disk('r2')->put('example.txt', 'Hello World');
    $text = env('CLOUDFLARE_R2_URL') . '/' . 'example.txt';
}
```

## 最後に
今回はR2をそのまま使いましたが、Workersを使うことでエグレス料金が無料になるみたいです。
(R2のクラスA、クラスB料金がかからない）

https://www.cloudflare.com/ja-jp/products/workers/

無料枠は1日10万リクエストなのでWorkersを利用した方がさらにお得になりそうです。
次回はWorkersを使ってエグレス料金を無料にする実装をまとめたいと思います。