【初心者向け】郵便番号で住所検索をする外部APIを叩く

#はじめに

実務でいつ使用してもいいように、ローカル環境で外部提供のAPIを叩く練習をしていきます。
あと、長いこと使用していないAjaxの復習もかねて。

今回は会員登録時に住所入力をサポートする、最近のデファクトスタンダードな仕様を目指してフォームの作成をしていきます。

#使用API
郵便番号検索API
http://zipcloud.ibsnet.co.jp/doc/api

※画面下部にAPI利用規約がありますので、使用する場合は一読するようにお願いします。

〜以下引用（2020年10月11日）〜
郵便番号検索APIは、日本郵便が公開している郵便番号データを検索する機能をRESTで提供しています。
現在使用しているデータは、「2020年9月30日更新分の全国一括データ（加工済バージョン）」です。

#環境+使用ライブラリなど
macOS Catalina 10.15.7
MAMP(Apache + MySQL)
PHP 7.3.11
jQuery(Ajax通信に使う)
Bootstrap(別に必要ではない)

#今回のゴールとする仕様

- 半角数字で7ケタの郵便番号を入力する。
- 「住所検索」ボタンを押す。
- 入力した郵便番号を使って外部APIを叩く
- レスポンスで受け取った情報をもとに、住所がフォームに自動入力される。
- クリアボタンを押すとフォーム全てがリセットされる（サービスにおいては必要なさそう）

#完成画面

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/588983/26c8890e-7834-6602-3888-f081ecc744f6.png)

#作成コード

```php:sample.php
<?php

  session_start();  // 今回の説明には不要

?>

<!DOCTYPE html>
<html lang="ja">
<head>
  <title>郵便番号検索API</title>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
  <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/css/bootstrap.min.css" integrity="sha384-9aIt2nRpC12Uk9gS9baDl411NQApFmC26EwAOH8WgZl5MYYxFfc+NcPb1dKGj7Sk" crossorigin="anonymous">
  <!-- Optional JavaScript -->
  <!-- jQuery first, then Popper.js, then Bootstrap JS -->
  <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
  <script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js" integrity="sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo" crossorigin="anonymous"></script>
  <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/js/bootstrap.min.js" integrity="sha384-OgVRvuATP1z7JjHLkuOU7Xw704+h835Lr+6QL9UvYjZE3Ipu6Tp75j7Bh/kR0JKI" crossorigin="anonymous"></script>
  <script src="postal_api.js"></script>
</head>
<body>
  <div class="container col-6">
    <h1 style="text-align: center; margin-top: 2.4rem; margin-bottom: 1.6rem">入力フォーム</h1>
    <div>
      <form method="post" action="#" style="width: fit-content; margin: 0 auto;">
        郵便番号<br />
        <input type="text" name="zip_code" style="width:100px" id="zip_code">
        <input type="button" value="住所検索" id="search_address_btn">
        <input type="button" value="クリア" id="search_clear_btn">
        <br />
        都道府県<br />
        <input type="text" name="address1" style="width:500px" id="address1"><br />
        市区町村<br />
        <input type="text" name="address2" style="width:500px" id="address2"><br />
        その他<br />
        <input type="text" name="address3" style="width:500px" id="address3"><br />
        建物名など<br />
        <input type="text" name="address4" style="width:500px"><br />
        <br />
        <div class="submit_button_right" style="text-align: right;">
          <input type="submit"><br />
        </div>
      </form>
    </div>
  </div>
  
</body>
</html>
```

見た目を少しででも整えるために
Bootstrap関係のタグが多いですが、以下のタグだけでも動作確認済みです。

```php
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script> //ajax通信用
<script src="postal_api.js"></script> //jsファイルの読み込み
```
<br />


読み込んでるjsのスクリプトはこんな感じです。

```javascript:postal_api.js

$(document).ready(function(){

    // 住所検索ボタンを押すと外部apiを叩く処理が走る。
    $('#search_address_btn').click(function() {
        $.getJSON('http://zipcloud.ibsnet.co.jp/api/search?callback=?',
            {
            zipcode: $('#zip_code').val()
            }
        )
        .done(function(data) {
            if (!data.results) {
                alert('該当の住所がありません');
            } else {
                let result = data.results[0];
                $('#address1').val(result.address1);
                $('#address2').val(result.address2);
                $('#address3').val(result.address3);
            }
        }).fail(function(){
            alert('入力値を確認してください。');
        })
    })
    
    // クリアボタンを押すと、フォームの中身がリセットされる。
    $('#search_clear_btn').click(function(){
        $('#zip_code').val('');
        $('#address1').val('');
        $('#address2').val('');
        $('#address3').val('');
    })
})
```

記事を書いてて、ふと
"クリアボタンとかいらなくね？"
と、思ったのは私だけでしょうか。また検索すればいいだけですよね。
なんなら、間違って押してしまったユーザーにとってはストレスでしかありません。

今回は、簡易的なフォームを作って動作を確認するためだけに実装しましたが、
実際のサービスでフォームの内容を考える場合はきちんとそのあたりも設計した方がいいですね。

あと、このままのコードで動作を実行すると
Chrome検証ツールのConsoleに、サードパーティーやCSRFによるリークに関する注意が　issueとして表示されます。
今回は個人的な動作確認なので、割愛。

#データ取得に関する説明

APIの提供元でサンプルの取得データが確認できます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/588983/62f16c21-8cda-9423-fce0-5540c7fbd78b.png)

一部見切れてしまっていますが、"message","results","status"という要素があります。
今回使いたいのはresultsの中身です。

```js
            } else {
                let result = data.results[0];
                $('#address1').val(result.address1);
                $('#address2').val(result.address2);
                $('#address3').val(result.address3);
            }
```

配列は[0]から始まるので、一旦、中身をresultという変数に置き換えます。
そして、レスポンスサンプルで確認できるように、address1〜address3をそれぞれフォームのvalueに入れてあげればいいわけです。

#注意事項
今回の例は配列の最初の要素を住所候補としてブラウザに返していますが、
場所によっては、同じ郵便番号でも住所が3パターン存在したりします。

例:0790177
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/588983/6dec2fc9-fe80-68a9-c4fd-036ae99321ae.png)

こういった場合は押した回数で分岐させるような構造がいいんでしょうか。
Amazonで試してみたら7ケタ目を入力した直後に住所検索の処理が走るので、上記の例だと上美唄町しか出てきませんでした。AmazonのAPIでは候補が一つだけなんですかね。


#実装中に詰まった部分

- 久しぶりにAjax触ったので、そもそも最初は流れが思い出せなかった。
- JSON形式でデータを受け取るにあたって、同じドメイン上のAPIしか叩いたことがなかったので、クロスドメインでAPIを叩く処理を実装する部分に時間がかかった。（記述はシンプルなので、検索して情報を見つけてからは大したことなかった）

#最後に

これで住所入力の手間が省けるフォーム部分が完成したので、実際使用する場合には他の項目と一緒にPOSTでphpスクリプトに送ってやればいいわけですね。

今回、①外部APIを叩く　②Ajaxの復習　という目的が無事達成できたので良かったです。
今後もこれぐらい軽めに取り掛かれる実装をプライベートでもガンガンやっていきたいと思います。

ここまで読んでいただきありがとうございました。

#参考

- [郵便番号検索API - zipcloud](http://zipcloud.ibsnet.co.jp/doc/api)
- [JSON形式のWeb APIにアクセスするには？（$.getJSON）](https://www.buildinsider.net/web/jqueryref/034)