あーる学習帳

自分が勉強したことや気になることなど、99%自分用です。コードを書いてるのでPCから閲覧を推奨。

PHP開発日記:しばらく住所録を作ります

作りたいものは1つ決まっているのですが、それまでにいくつかの過程を踏まなければならないようです。

  • PHPの基礎的な書き方(昨日までの学習)
  • TwitterAPIと会員登録システムの組み合わせ
  • 簡易的な検索エンジン
  • その他必要に応じて付け足し

APIの話は一朝一夕ではできる気がしないので、まずは「簡易的な検索エンジン」から取り組んでいきます。

日本郵便の公式ホームページで日本全国の住所録をcsv形式で手に入れることができるので、これを使って日本全国の住所を検索するシステムを作ります。

 要件定義

  1. 日本郵便のホームページから全国の住所一覧を入手、それをMySQLに取り込み。
  2. 検索条件を入力するため、「都道府県を選択するコンボボックス」「市町村以下をフリーワード検索するための入力欄」を用意する。
  3. 検索結果を表示するページではGoogleやYahooのように、検索してヒットした件数が多くなる場合は10件ごとに1ページ表示すること。検索してヒットしなかった場合、エラーを出す。
  4. 条件を入力するページと結果を表示するページは同じページとする(Googleで画面上部に検索ボックス、その下に結果が表示されるようなイメージ)

 まずは日本全国の住所を入手。

www.post.japanpost.jp

ここから全国の住所が入った「ken_all.zip」を入手し、解凍して「ken_all.csv」を取り出す。カンマで区切られた各項目の説明は以下の通り。

郵便番号データの説明 - 日本郵便より引用。

  • 全国地方公共団体コード(JIS X0401、X0402)……… 半角数字
  • (旧)郵便番号(5桁)……………………………………… 半角数字
  • 郵便番号(7桁)……………………………………… 半角数字
  • 都道府県名 ………… 半角カタカナ(コード順に掲載) (注1)
  • 市区町村名 ………… 半角カタカナ(コード順に掲載) (注1)
  • 町域名 ……………… 半角カタカナ(五十音順に掲載) (注1)
  • 都道府県名 ………… 漢字(コード順に掲載) (注1,2)
  • 市区町村名 ………… 漢字(コード順に掲載) (注1,2)
  • 町域名 ……………… 漢字(五十音順に掲載) (注1,2)
  • 一町域が二以上の郵便番号で表される場合の表示 (注3) (「1」は該当、「0」は該当せず)
  • 小字毎に番地が起番されている町域の表示 (注4) (「1」は該当、「0」は該当せず)
  • 丁目を有する町域の場合の表示 (「1」は該当、「0」は該当せず)
  • 一つの郵便番号で二以上の町域を表す場合の表示 (注5) (「1」は該当、「0」は該当せず)
  • 更新の表示(注6)(「0」は変更なし、「1」は変更あり、「2」廃止(廃止データのみ使用))
  • 変更理由 (「0」は変更なし、「1」市政・区政・町政・分区・政令指定都市施行、「2」住居表示の実施、「3」区画整理、「4」郵便区調整等、「5」訂正、「6」廃止(廃止データのみ使用)

この中で「3.郵便番号」「7.都道府県名(漢字)」「4.都道府県名(半角カナ)」「8.市区町村名(漢字)」「5.市区町村名(半角カナ)」「9.町域名(漢字)」「6.町域名(半角カナ)」を取り出し、取り込み用のPHPファイルを作ってMySQLに取り込む。余力があればcsvファイルをアップロードするボタンを作って、「ローカル環境から仮想環境へファイルをアップロード→それを取り込み」という機能もいいかもしれない。取り込むかどうかの判断が難しそうだけど…。

なお、町域名に「以下に掲載がない場合」と入っているレコードも存在している。これについては取り込みの段階で弾くようにしたい。

取り込み先となるMySQLのデータベースとテーブルを作成する。

データベース名:address

テーブル名:address

テーブル構成

addno varchar(7) primary key…郵便番号、主キーとする

add1 varchar(255)…都道府県名(漢字)

add1kana varchar(255)…都道府県名(半角カナ)

add2 varchar(255)…市区町村名(漢字)

add2kana varchar(255)…市区町村名(半角カナ)

add3 varchar(255)…町域名(漢字)

add3kana varchar(255) …町域名(半角カナ)

 インデックスは考えずに作成。

次にPHP側を作成。

昨日までの学習内容を参考にconfig.phpを作成し、定数の設定を行う。

 <?php

//Config.php

// 住所録用定数
define('DSN','mysql:dbname=address;host=localhost');
define('DB_USER','user');
define('DB_PASS','aaaa');
define('SITE_URL','http:192.168.33.11:8000');

error_reporting(E_ALL & ~E_NOTICE);

 今回はセッションは使わない予定なので、今のところは設定していない。

これまでと同様、MySQL接続用のヘルパーファイルも作成。

 <?php

 //db_helper.php
 function get_db_connect(){
  try {
   $dsn=DSN;
   $user=DB_USER;
   $password=DB_PASS;
   $dbh=new PDO($dsn,$user,$password);
  } catch (PDOException $e) {
   echo $e->getMessage();
   die();
  }
  $dbh->setAttribute(PDO::ATTR_ERRMODE,ERRMODE_EXCEPTION);
  return $dbh
}

 HTML表示用の関数も別のヘルパーファイルに作成する。

<?php

//extra_helper.php
 function html_escape($word){
  return htmlspecialchars($word,ENT_QUOTES,'UTF-8');
 } 

とりあえずはこれだけ、必要があれば適宜追加していく。

まずはcsv取り込み用のページを作る。

定数に以下のフラグとなる定数を設定し、index.phpを開いたときにこの定数をチェック→csv取り込みに飛ぶか検索に飛ぶかを判断する。

//config.php

//住所録設定関連
define('GETCSV','ON');  //ON→CSV取り込み、OFF→検索

index.phpには以下のように記述。

 <?php

 //index.php

 //設定&関数読み込み
 require_once('config.php');
 require_once('./helpers/db_helper.php');
 require_once('./helpers/extra_helper.php');

 if (GETCSV==='ON') {
  header('Location:'.SITE_URL.'csvget.php');
  exit();
 } else {
  header('Location:'.SITE_URL.'search.php');
  exit();
 }

フラグに応じてリダイレクト先を変えるようにした。

いよいよcsvget.phpを作成する。csvget.phpディレクトリに「csv」というフォルダを作り、そこに先ほど取得したken_all.csvをアップロードしてある。

<?php
 require_once('config.php');
 require_once('./helper/db_helper.php');
 require_once('./helper/extra_helper.php');
 //csv読み込み処理
 $file=@fopen('./csv/KEN_ALL.CSV','r') or die('ファイルを開けませんでした');
 //var_dump($file);
 flock($file,LOCK_SH);
 //とりあえず画面に出してみよう
 while (!feof($file)) {
  $line=fgets($file);
  echo '<p>'.$line.'</p>';
 }
 flock($file,LOCK_UN);
 fclose($file); 

ファイル名については大文字小文字の判定までしているので、ファイル名に合わせて書く。登録の前にとりあえず画面に表示を…と思ったが、文字化けでひどい有様に。

f:id:R_de_aru:20180710233003p:plain

今まで文字コードUTF-8だったけど、今回はなんだか違うような気がする…。

明日はこの文字化けの解消法を探る。画面に出すところまではできているので、文字化けさえ解消できれば登録もすぐ出来そう。