アップしたファイル名が文字化けしてmbstring.encoding_translationで直した件

ずいぶん昔に作ったEUC-JPのシステムで、SJISのファイルをアップして一覧で管理しているところがあるんだけど、ある時期から急にアップしたファイル名が文字化けするようになってしまった。
レンタルサーバー会社に確認すると、その頃にメンテをしたらしくて、おそらくそのせいでなってしまったのだろう。

というわけで、実環境と開発環境のphpinfo()を比較してみたら実環境で mbstring.encoding_translation が On になっていたので、Off に変更したところ、文字化けが解消した。
以下は .htaccess への記述

php_value mbstring.encoding_translation    Off

それで、これについてPHPマニュアルで調べてみると、
http://php.net/manual/ja/mbstring.http.php

「mbstring.encoding_translation に On が指定されている場合、 POST データの変数とアップロードされたファイルの名前の文字エンコーディングは、 内部文字エンコーディングに変換されます。」

と書いてあった。なるほど、そうだったのか。

mysql から mysqli への移行

過去の遺産がまだ残っているシステムを少しずつ新しくいるところ。
今回は mysql 関数を使っていた部分を mysqli 関数に書き換えた。
手続き型の記法だけど・・
まだ今頃こんなことやってるけど、やらないよりは遥かに良い。

DB接続の部分は少し書き方が変わる。
クエリー発行とエスケープの部分は引数が変わる。
僕が使っている関数の範囲では、あとは単に関数名を置き換えるだけで済んだ。

/* DB接続 --------------------- */

$con = mysql_connect($dbserver, $dbuser, $dbpassword);
$selectdb = mysql_select_db($dbname);
         ↓↓↓
$con = mysqli_connect($dbserver, $dbuser, $dbpassword, $dbname);

/* 引数が異なる --------------------- */

mysql_query($sql);
         ↓↓↓
mysqli_query($con, $sql);

mysql_real_escape_string($str);
         ↓↓↓
mysqli_real_escape_string($con, $str);

/* 関数名置き換えのみ --------------------- */

mysql_fetch_array($rst)
         ↓↓↓
mysqli_fetch_array($rst)

mysql_num_rows($rst)
         ↓↓↓
mysqli_num_rows($rst)

mysql_free_result($rst);
         ↓↓↓
mysqli_free_result($rst);

クラス作ってるのが接続のところだけなんで、他の各関数はあっちこっちのファイルに沢山書いてあったから、順次置換作業を行って無事移行できた。

PHPページから別のPHPの出力をcURLで取得する

CodeIgniter(CI)アプリケーションのindex.phpをサイトの /sys/ 以下に配置して、ルートにある静的HTML(PHP)のページからCIのデータを呼び出して使うようにしているシステムがあって、
その時にAjaxでデータを取りに行くように作っていたのだけれど、よく考えると file_get_contents() や cURLを使えばPHPページからいきなり取りに行けるじゃないか!と気づいて(汗)、取得部分をcURLを使って書き換えた。
忘れないうちに覚え書きとして書いておく。

$url = 'https://xxxxxxx/json';

$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url); // ---(1)
curl_setopt($ch, CURLOPT_USERPWD, 'user:password'); // ---(2)
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); // ---(3)
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); // ---(4)
$result = json_decode(curl_exec($ch)); // ---(5)

// その後の処理

curl_close($ch);

curl_setopt() のオプション等の補足説明

(1) 取得するデータのURL
(2) 今回Basic認証をかけているのでその認証用のユーザー名とパスワード
(3) curl_exec() の戻り値が取得結果になるように true を設定
(4) サーバー証明書の検証を行わないように false を設定
(5) もともとAjaxに対して結果がjsonで返るようにしていたので、そのjsonをオブジェクトに変換して取得

以上でめでたくAjaxからcURLでの取得に置き替えることができた。

市区町村APIを利用するときの注意点

エリア情報を検索する際に、市区町村で検索したい場合がある。
今回は、

1. 都道府県のセレクタ → 都道府県を選ぶ
2. 上記に含まれる市区町村のセレクタ → 市区町村を選ぶ

といった機能が必要だったので、APIを使用して実装した。
(自分で市区町村データを作るのはとても無理)

(1) 国土交通省 土地総合情報システム 都道府県内市区町村一覧取得API
http://www.land.mlit.go.jp/webland/api.html#todofukenlist

(2) 内閣府 地方創生推進室 RESAS-API の「都道府県一覧」と「市区町村一覧」
https://opendata.resas-portal.go.jp/docs/api/v1/index.html

僕は最初、(1)を使用して作ったのだが、政令指定都市の場合、例えば「大阪市」と同じ並びで「中央区」となり、「中央区」を選択すると「中央区」だけの表示になって、どこの中央区かよく分からない状況になってしまった。
APIの情報に政令指定都市かどうかの区別もないので、後から加工するのも困難だった。

なので、(2)を使用してみたところ、そのままで「大阪市中央区」という表示が出せるようになったので助かった。
別に政令指定都市のフラグも設けられているので、その辺りのハンドリングはしやすいと思う。

あと、(1)の場合は都道府県コード一覧のAPIがないので自分で配列を作ったりしたが、(2)の場合はそれがあるので自分でデータを用意する必要はなかった。

(1)の国土交通省のAPIは、利用登録も必要なくすぐに使えて便利そうだけど、市区町村の情報が足りないから僕みたいな使い方の場合はあとで困る。
(2)の内閣府のAPIは、利用登録をしてAPIキーを取得する必要があるけれど、政令指定都市の区別があるので何かと使い回しやすいと感じた。

(1)から(2)に移行する時は、データの構成はよく似ているのでさほど苦労はしなかった。ほとんどロジックそのままで、一部、オブジェクトのプロパティ名や階層を変えるぐらいの軽微な変更で差し替えることができた。

ユーザーの検索時に毎回APIにアクセスするのは気が引けるので、一度全部の情報をサーバー上に保存(つまりキャッシュ)してそのデータにユーザーからアクセスしてもらうように作った。
その一式のダウンロードの時間は、(2)の方が倍くらい長いように感じた。