【Laravel11】スプレッドシートへの書き込み

# はじめに
本記事ではLaravelでフォーム送信されたデータをスプレッドシートに書き込む手順をご紹介します。先日仕事で触れた内容でしたので、忘れないうちに備忘録として残しておきます。使用環境は以下です。
* Laravel11系
* PHP8.2系
* mac
* docker（sailコマンドを使用）

# 手順
スプレッドシートへの書き込みは以下の手順で実装していきます。
1. google APIでスプレッドシートを有効化
1. スプレッドシートAPIの認証ファイルを取得
1. 書き込み用のスプレッドシートを作成
1. laravelでライブラリをインストール
1. 書き込み処理を実装

# google APIでスプレッドシートを有効化
まずはご自身のgoogleアカウントから[Google Cloud](https://console.cloud.google.com/)のコンソールへログインします。私の場合はすでにプロジェクトを作成しているので、最近使用したプロジェクトが開かれた状態になってます。上部にプロジェクト選択メニューがあるので開きましょう。
![image1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3364507/4ea4aa44-170e-77f7-9cb5-501ea283b072.png)
「新しいプロジェクト」をクリックして適当なプロジェクト名で作成します。
![image2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3364507/6167a2e6-1a42-b8a9-6396-ce31d7e74a84.png)
![スクリーンショット 2025-01-11 9.39.57.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3364507/6f2d4d8b-33b5-cf78-51e8-6725b2d56a36.png)
プロジェクトが作成されたら、そのプロジェクトを選択した状態でAPIのメニューを開きます。
![image3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3364507/41f23cc9-24c4-20bb-b639-fcf0288b8250.png)
setts APIを有効化します。
![image4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3364507/a051078c-9d1f-0848-657e-d521e5c2b874.png)
![image5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3364507/4e046bd3-7c44-7759-bba6-dee9a66e65fd.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3364507/65c19c26-72dd-fbd0-3560-713dafd10ab4.png)
![image6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3364507/c0f4c731-6eb5-9adf-3ca4-57f43dd791b9.png)

# スプレッドシートAPIの認証ファイルを取得
APIの有効化ができましたので、認証情報を作成します。
![image7.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3364507/0a522dd7-5709-74b7-5885-2a1edccc78b9.png)
アクセスするデータ種類はアプリケーションデータを選択してください。サービスアカウント名はお好みで
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3364507/d77c9131-391c-1838-eb3d-badf164ac308.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3364507/dc8a811c-49e2-f017-6085-7d109dee50b3.png)
ロールは今回はオーナーにします。実務ではプロジェクトに応じて適切な権限を設定してください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3364507/408b05fc-df20-1268-01dd-63adf633a21a.png)
サービスアカウントの許可はスキップします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3364507/65707057-2225-b634-4793-c60cda55bfc8.png)
サービスアカウントが発行されたので、次はアプリケーション側で必要な認証ファイルを作成します。
認証情報メニューから先ほど発行したアカウントを選択してください。
![image8.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3364507/3f048948-913c-f156-dc50-c31ecc204ee5.png)
「鍵」タブからキーを追加し、jsonファイルをダウンロードしてください。これでGCP側の設定は完了です。
![image9.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3364507/a57404f5-457e-0aa2-66f5-6884f83b511b.png)
![image10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3364507/018a95cc-6487-97fa-9acd-d1cd8fe282a7.png)

# 書き込み用のスプレッドシートを作成
ここはスプレッドシートを新規作成するだけなのでサクサクっと！
新規でスプレッドシートを作成し、先ほどのサービスアカウントのメールアドレスを編集者に追加してあげるだけです
![image11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3364507/7cfef897-0a2e-78ef-decc-f800048fde5c.png)
今回は名前、メールアドレス書き込むとしましょう。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3364507/42666f5c-63ea-c0ac-a1f7-93a15fe05c1c.png)

# laravelでライブラリをインストール
ではここからはLaravel側の作業です。プロジェクトを作成されている前提です。
まずはgoogle API用のライブラリをインストールします。ライブラリの詳細は[こちら](https://github.com/googleapis/google-api-php-client?tab=readme-ov-file)を参照してください。
```
composer require google/apiclient
```

# 書き込み処理を実装
.envとconfigにSPREADSHEET_IDを追加します。SPREADSHEET_IDはスプレッドシートのURLの`https://docs.google.com/spreadsheets/d/（スプレッドシートのID）/edit#gid=0`の部分です。
```.env
SPREADSHEET_ID=ご自身のスプレッドシートID
```
```config/services.php
<?php

return [

    //...省略
    'spreadsheet' => [
        'sheet_id' => env('SPREADSHEET_ID'),
    ],

];
```
スプレッドシート書き込む用のサービスクラスを定義します。このクラスのインスタンスをコントローラーで使用してスプレッドシートに書き込んでいきます。
```app/Services/googleSheetService.php
<?php

namespace App\Services;

class GoogleSheetService
{
    public static function instance() 
    {
        $credentials_path = storage_path('app/private/jsonファイル名');
        $client = new \Google_Client();
        $client->setScopes([\Google_Service_Sheets::SPREADSHEETS]);
        $client->setAuthConfig($credentials_path);

        return new \Google_Service_Sheets($client);
    }
}

```
また、こちらの記述にてダウンロードしたjsonファイルを使用します。ファイルパスは適切な設定をすればどこでもいのですが、セキュアなファイルなので私はstogrageのprivateフォルダに格納します。

:::note info
jsonファイルを複数人で共有する場合、git管理は避けた方がいいでしょう。理由は上述の通り、セキュアなファイルだからです。
:::

書き込み処理のコントローラーを定義します。今回は簡易的にするためバリデーションチェックは省略します。また、Userモデルを想定してリクエストを処理します。
モデル、コントローラー、ビューは以下です。
```app/http/controllers/SpreadSheetController.php
<?php

namespace App\Http\Controllers;

use App\Models\User;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;

class SpreadSheetController extends Controller
{
    public function index()
    {
        return view('index');
    }

    public function store(Request $request)
    {
        $user = new User([
            'name' => $request->name,
            'email' => $request->email,
        ]);

        $user->writeSpreadSheet();

        return to_route('spreadsheet.index');
    }
}
```
```/app/http/Models/User.php
<?php

namespace App\Models;

// use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use App\Models\GoogleSheet;
use App\Services\GoogleSheetService;

class User extends Authenticatable
{
    /** @use HasFactory<\Database\Factories\UserFactory> */
    use HasFactory, Notifiable;

    /**
     * The attributes that are mass assignable.
     *
     * @var list<string>
     */
    protected $fillable = [
        'name',
        'email',
        'password',
    ];

    /**
     * The attributes that should be hidden for serialization.
     *
     * @var list<string>
     */
    protected $hidden = [
        'password',
        'remember_token',
    ];

    /**
     * Get the attributes that should be cast.
     *
     * @return array<string, string>
     */
    protected function casts(): array
    {
        return [
            'email_verified_at' => 'datetime',
            'password' => 'hashed',
        ];
    }

    public function writeSpreadSheet()
    {
        $sheets = GoogleSheetService::instance();
        $sheet_id = config('services.spreadsheet.sheet_id');

        $output = [
            $this->name,
            $this->email,
        ];

        $values = new \Google_Service_Sheets_ValueRange();
        $values->setValues([
            'values' => $output,
        ]);
        $params = ['valueInputOption' => 'USER_ENTERED'];
        $sheets->spreadsheets_values->append(
            $sheet_id,
            'A1',
            $values,
            $params
        );
        
    }
}
```
```resources/views/index.blade.php
<form action="{{ route('spreadsheet.store') }}" method="post">
    <input type="text" name="name" placeholder="Name">
    <input type="email" name="email" placeholder="Email">
    <button type="submit">Submit</button>
</form>
```
一応ルーティングも載せておきます。
```routes/web.php
<?php

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

Route::resource('spreadsheet', SpreadSheetController::class)->only(['index', 'store']);

```
では動かしてみます。`http://localhost/spreadsheet`にアクセスし、適用な値を入力して送信！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3364507/134f37d8-a86b-c307-7413-965ecdc3bec6.png)
書き込み成功です！あとはご自身のすきな値にカスタマイズしてください！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3364507/ef2640e5-ee15-b87b-7e24-8843846364af.png)

# まとめ
最後までご覧いただきありがとうございます！DBを使用するほどではないから、スプレッドシートにデータを貯めておきたい場合などに使えるのではないかなと思います。もし本記事に誤りがございましたらご教示いただけますと幸いです。最後になりますが、[こちら](https://qiita.com/oono_dev/items/bf647cb77b65764d14c5)の記事にて私が普段どんな心構えで仕事に臨んでいるかを書いていますので、よければ覗いてみてください！また、本記事で取り扱ったソースコードの全量はgithubをご覧いただければと思います。

https://github.com/oono-dev/laravel-spreadsheet-sample