#はじめに
実務で表題の通り、郵便データをCSVファイルから読み取り、住所データをDBに一括登録する場面があったので、その方法をご紹介致します。
今回は下記リンクから飛べる、読み仮名データの促音・拗音を小書きで表記するものの中にあるken_all.zipという全国一括版のファイルをダウンロードしました
環境
Laravel 8.*
MySQL5.7
#データをダウンロードする
全国一括(KEN_ALL.CSV)というファイルをZIPファイルを展開する。
展開したファイルを laravelプロジェクトディレクトリ/storage/app/csv直下に配置し、Laravelからファイルを読み込むようにする。
#住所データを保存するテーブルを作成
下記コマンドを実行して、住所データを格納する為のマイグレーションファイルと、モデルを同時に作成
database/migrations内にxxxx_xx_xx_xxxxxx_create_postal_codes_table.phpというファイルができているので、up()の中身を下記のように変更してphp aritsan migrate
を実行する。
public function up()
{
Schema::create('postal_codes', function (Blueprint $table) {
$table->increments('id');//オートインクリメントで連番
$table->unsignedInteger('first_code')->index();//郵便番号の始め(3桁)の部分
$table->unsignedInteger('last_code')->index();//郵便番号の後ろ(4桁)の部分
$table->string('prefecture');//都道府県名
$table->string('city');//市区町村
$table->string('address');//それ移行の住所
});
}
先程作成したモデルは下記のように変更
namespace App;
use Illuminate\Database\Eloquent\Model;
class PostalCode extends Model
{
public $timestamps = false;//マスタデータとして使用するので不要とのことだったので、timestampsをfalseに指定。
protected $guarded = ['id'];//データ追加時に思わぬエラーが起きないようidを指定
}
ここまでの手順で、住所データをDBに登録する為の土台が出来上がりました。
(住所登録用のテーブルとモデルが完成)
#CSVファイルから郵便データを読み取り、DBへ一括登録
日本郵便のデータは頻繁に更新されているようなので、その都度更新が出来るよう郵便データ登録用のコマンドを作成します。
php artisan make:command ImportPostalCodeCommand
次に、app/Console/Commands/ImportPostalCodeCommand.phpを開いて、中身を下記のように変更します。
<?php
namespace App\Console\Commands;
use Illuminate\Console\Command;
class ImportPostalCodeCommand extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'import:postal-code';//コマンド実行名
/**
* The console command description.
*
* @var string
*/
protected $description = 'Import postal-code';//コマンドの説明内容
/**
* Create a new command instance.
*
* @return void
*/
public function __construct()
{
parent::__construct();
}
/**
* Execute the console command.
*
* @return mixed
*/
public function handle()
{
// 登録処理の前にテーブルを一旦、空にする
\App\PostalCode::truncate();
// CSVファイルの文字コード変換
$csv_path = storage_path('app/csv/KEN_ALL.CSV');//先程ダウンロードしたCSVファイルのパスを書く
$converted_csv_path = storage_path('app/csv/postal_code_utf8.csv');//CSVファイルの文字コードをSJIS-winからUTF-8に変換した後のファイル名を指定
file_put_contents(
$converted_csv_path,
mb_convert_encoding(
file_get_contents($csv_path),
'UTF-8',
'SJIS-win'
)
);
// 文字コードを変換したCSVファイルから郵便データを取得してDBへ保存
$file = new \SplFileObject($converted_csv_path);
$file->setFlags(\SplFileObject::READ_CSV);
foreach ($file as $row) {
if (!is_null($row[0])) { //空行の場合、登録処理の際にエラーが発生することがあるので条件分岐させる
\App\PostalCode::create([
'first_code' => intval(substr($row[2], 0, 3)),
'last_code' => intval(substr($row[2], 3, 4)),
'prefecture' => $row[6],
'city' => $row[7],
'address' => (str_contains($row[8], '(')) ? current(explode('(', $row[8])) : $row[8]
]);
}
}
}
}
php artisan import:postal-code
を実行して郵便データを移動させます。(全12万件と、データ量がとても大きいので、登録処理に少し時間がかかるのと、大規模のデータを登録するのでテーブルの削除処理から登録までにトランザクションを張った方が良いかと思います。(下記のような形で)
以上で、郵便データの登録処理が完了致しました。作業に取りかかるまでは難しそうなイメージでしたが、いざ終わってみると意外と簡単という感想です。
今回は実務として着手することはなかったのですが、個人で住所検索処理の実装などもやってみます。
ここまで読んで頂きありがとうございます。今後ともメモ代わりに書いていけたらと思っておりますので宜しくお願い致します。