【Laravel】郵便番号から住所を自動入力する機能の作り方
Laravelで郵便番号から住所を自動入力する機能を作る。LaravelでAPIを作ってJavaScriptからAPIを叩くことで実現する。
郵便番号と住所のデータを入手する
まずは,以下からデータを入手する。
全国一括データ (加工済バージョン)をダウンロードして,x-ken-all.csvを開く。
必要なのは,C,G,H,Iの4列だけなので,その他の列は削除する。
[名前を付けて保存]を選び,ファイル形式をCSV UTF-8で保存する。
データの置き場所はdatabase/seedersにする。
マイグレーションとモデルの作成
マイグレーションファイルを作成。
$ sail artisan make:migration create_addresses_table
マイグレーションファイルを編集。
public function up()
{
Schema::create('addresses', function (Blueprint $table) {
$table->id();
$table->integer('zip');
$table->string('pref');
$table->string('city');
$table->string('town');
$table->timestamps();
});
}
マイグレーションを実行。
$ sail artisan migrate
モデルを作成。
$ sail artisan make:model Address
seederの作成と実行
seederを作成する。
sail artisan make:seeder AddressesSeeder
<?php
namespace Database\Seeders;
use Illuminate\Database\Console\Seeds\WithoutModelEvents;
use Illuminate\Support\Facades\DB; <--これを入れ忘れないように
use Illuminate\Database\Seeder;
class AddressesSeeder extends Seeder
{
/**
* Run the database seeds.
*
* @return void
*/
public function run()
{
$this->command->info("addressesの作成を開始します...");
$memberSplFileObject = new \SplFileObject(__DIR__ . '/x-ken-all.csv');
$memberSplFileObject->setFlags(
\SplFileObject::READ_CSV |
\SplFileObject::READ_AHEAD |
\SplFileObject::SKIP_EMPTY |
\SplFileObject::DROP_NEW_LINE
);
foreach ($memberSplFileObject as $key => $row) {
//excelでcsvを保存するとBOM付きになるので削除する
if ($key === 0) {
$row[0] = preg_replace('/^\xEF\xBB\xBF/', '', $row[0]);
}
DB::table('addresses')->insert([
'zip' => (int) trim($row[0]),
'pref' => trim($row[1]),
'city' => trim($row[2]),
'town' => trim($row[3]),
]);
}
$this->command->info("addressesを作成しました。");
}
}
seederを実行する。
$ sail artisan db:seed --class=AddressesSeeder
レコードが12万件ほどあるので処理が終了するまでしばらく待つ。以下のメッセージが出れば成功。
addressesの作成を開始します...
addressesを作成しました。
Database seeding completed successfully.
ルーティング
ルーティングを追加。web.phpではなくapi.phpに書き込む。ここでは省略するが顧客情報の入力などで利用する場合はユーザー認証しないとアクセスできないようにミドルウェア->middleware(['auth'])
を挿入することになる。
use App\Http\Controllers\Api\AddressController;
Route::get('/address/{zip}', [AddressController::class, 'address']);
コントローラーの設置
コンロトーラーを設置する。APIでCRUD機能を設置する場合はオプション --api
を付けると便利だが,今回は目的が異なるので不要。
$ sail artisan make:controller Api/AddressController
<?php
namespace App\Http\Controllers\Api;
use App\Http\Controllers\Controller;
use App\Models\Address; <--これを入れ忘れないように
use Illuminate\Http\Request;
class AddressController extends Controller
{
public function address($zip)
{
$address = Address::where('zip', intval($zip))->first();
return response()->json(
$address,
200,
[],
JSON_UNESCAPED_UNICODE
);
}
}
これでAPIの設置は完了。
APIのテスト
ここで,APIがちゃんと動いているかどうかを確認する。
アドレスバーに http://localhost/api/address/640803
と入力して
{"id":52,"zip":640803,"pref":"北海道","city":"札幌市中央区","town":"南三条西","created_at":null,"updated_at":null}
が表示されればAPIが機能している。
ビューの設置
郵便番号から住所を自動入力する機能はユーザーの新規登録などで利用する。ここでは話を省略するためにユーザーのテーブルは作成せず,郵便番号を入力したら住所をフィールドに挿入するだけのコードを紹介する。
まずは,ビューの作成。
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
</head>
<body>
<p>郵便番号:<input id="zip" type="text" name="zip" size="7">例:1020072(半角数字)</p>
<button class="api-address" type="button">住所を自動入力</button>
<p>住所:<input id="address" type="text" name="address" size="30"></p>
</body>
<script>
//イベントリスナの設置:ボタンをクリックしたら反応する
document.querySelector('.api-address').addEventListener('click', () => {
//郵便番号を入力するテキストフィールドから値を取得
const elem = document.querySelector('#zip');
const zip = elem.value;
//fetchでAPIからJSON文字列を取得する
fetch('../api/address/' + zip)
.then((data) => data.json())
.then((obj) => {
//郵便番号が存在しない場合,空のオブジェクトが返ってくる
//オブジェクトが空かどうかを判定
if (!Object.keys(obj).length) {
//オブジェクトが空の場合
txt = '住所が存在しません。'
} else {
//オブジェクトが存在する場合
//住所は分割されたデータとして返ってくるので連結する
txt = obj.pref + obj.city + obj.town;
}
//住所を入力するテキストフィールドに文字列を書き込む
document.querySelector('#address').value = txt;
});
});
</script>
</html>
話を省略するためにJavaScriptのコードを直接書き込んでいるが,本来はファイルを分けた方が良い。
これで完成。
SNSでシェア