zipcloudとLivewireを使った住所の自動入力がうまくいかないときの解決策

## はじめに
[zipcloud（郵便番号検索API）](https://zipcloud.ibsnet.co.jp/doc/api)と[Livewire](https://laravel-livewire.com/)を使用して、郵便番号から住所が自動入力される機能を実装したかったのですが、なかなかフォームに住所が反映されずに苦戦してしまいました。

最終的には、非常にシンプルな方法で解決しました！

## 環境
- Laravel 10
- PHP 8.1
- Docker

## 結論
resources/js/app.jsから以下の行を削除する

```diff_javascript
import './bootstrap';

- import Alpine from 'alpinejs';
- window.Alpine = Alpine;
- Alpine.start();

```

## 詰まった箇所
APIから取得した住所がフォームに反映されない
（スタイルはテキトーですのであしからず）

<img width="350" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3783222/d06b27c3-c53a-25e8-6163-9b48525c3c6a.png" />

## 試したこと、調べたこと

### 自動入力の仕組み
今回の本題とズレるため超ざっくりとした解説ですが、以下のような流れです。
あらかじめ自動入力ボタンにはwire:clickを設定しておきます。
1. 郵便番号7桁を入力し「自動入力」を押下
1. LaravelのHttpファサードを使用し、APIから住所情報を取得
1. 正常に取得できたらプロパティに都道府県・市区町村・町名をセット
1. ビューにwire:modelを設定しているため、3でプロパティが更新されたらフォームに住所が自動入力される

```php
public function searchAddress()
{
    $response = Http::get("https://zipcloud.ibsnet.co.jp/api/search", [
        'zipcode' => $this->zipcode
    ]);

    if ($response->successful() && $response->json()['status'] === 200 && !empty($response->json()['results'])) {
        $result = $response->json()['results'][0];

        $this->prefecture = $result['address1'];
        $this->city = $result['address2'];
        $this->town = $result['address3'];
    } else {
        session()->flash('error', '郵便番号に該当する住所が見つかりません。');
        $this->reset(['prefecture', 'city', 'town']);
    }
}
```

理論上はこれでうまくいくはずなのですが、laravelのエラーこそ出ないもののフォームに住所が表示されません。

<img width="350" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3783222/bf0de910-9c50-94bd-7aea-222062151269.png">

### ログの確認
APIからデータが正しく取得できているかどうかを確認するために、render()メソッドに以下のコードを追加します。

```diff_php
public function render()
    {
+       \Log::info($this->prefecture);
+       \Log::info($this->city);
+       \Log::info($this->town);
        return view('livewire.zipcode-auto-complete');
    }
```

これでstorage/log/laravel.logにログが残るようになります。

ふつうに郵便番号を入力して自動入力を押してみると、ちゃんと住所は取得できていました。

```text:laravel.log
[2024-10-27 10:35:58] local.INFO: 東京都  
[2024-10-27 10:35:58] local.INFO: 千代田区  
[2024-10-27 10:35:58] local.INFO: 千代田 
```

どうやら、livewireでリアルタイム表示する箇所がバグっているようですね。

## 解決策を試す
開発者ツールでコンソールを見ると、以下のような警告が出ていました。
![スクリーンショット 2024-10-27 19.49.12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3783222/b3130a4b-6887-bbfd-3c18-346aae0f1b83.png)

Alpine.jsが重複して読み込まれていることが原因のようです。

自分の場合は認証機能としてLaravel Breezeをインストールしていたのですが、
BreezeとLivewireの両方で「Alpine.js」を読み込んでいたため、衝突が起きていたようです。

冒頭に書いたとおりresources/js/app.jsから以下の行を削除すると...
動きました！

```diff_javascript
import './bootstrap';

- import Alpine from 'alpinejs';
- window.Alpine = Alpine;
- Alpine.start();
```

<img width="350" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3783222/789080ba-09e9-d76a-3ab5-2e0c647c05e0.gif">

（本記事と関係ないのですが、zipcloudは郵便番号が数字7桁でも、XXX-YYYYというハイフンを含む形でも検索できます。便利ですね）

## おわりに
今回のケースは画面上にエラーが出ていたわけではないので、原因を突き止めるのに色々と回り道をしてしまいました。

また、Laravelで住所検索・自動入力機能を実装する方法については、ググってもなかなかベストな情報が見つからず、そこも苦戦したポイントでした。

次はこの住所検索・自動入力機能について詳しく記事にしたいと思います〜！


## 参考
- [郵便番号データ配信サービスzipcloud](https://zipcloud.ibsnet.co.jp/doc/api)
- [Error: Detected multiple instances of Alpine running. ( Livewire 3.x & Laravel 11.x )](https://stackoverflow.com/questions/78389150/error-detected-multiple-instances-of-alpine-running-livewire-3-x-laravel-1)