SJISのファイルをUTF8のDBにロードする目的でした。
失敗する可能性が高い例
何も考えないで書くと、こんな感じにデータを入れる直前で文字列変換するように書いてしまいがちですが、これだと文字化けで改行が崩れたりします。
$fp = fopen("example.csv", 'r');
while ($data = fgetcsv($fp, 10000)) {
foreach( $data as $index=>$value) {
// カラムごとにUTF8に変換
$data[$index] = mb_convert_encoding($value, "UTF-8", "SJIS");
}
// DBにinsertとかupdateとか
}
fgetcsvで1行フェッチしてcsvをパースして配列に入れるタイミングで、まだ文字コードSJISのままです。
この操作でCSVの行が次の行とくっついたりしてハマることがあります。それを回避するために文字エンコーディングを変換してから一行ずつ読むように処理を変更します。
正しくパースできるようにする
fgetcsvが1行を読む時(ストリームを読むとき)に文字コードを変換しつつ読み出すフィルターを設定します。
フィルタは、php_user_filterというクラスをExtendして実装しないといけないのですが、その実装は、すでに先人の皆々さまによって用意していただいているものを拝借。最高。
stream_filter_register — ユーザー定義のストリームフィルタを登録する
http://php.net/manual/ja/function.stream-filter-register.php
Stream_Filter_Mbstring
http://openpear.org/#stream_filter_mbstring
クラスの中身はこちらと同じかな?
github : Stream_Filter_Mbstring - mbstringを使って文字列変換を行うstream filter
https://github.com/xcezx/Stream_Filter_Mbstring/blob/master/src/Stream/Filter/Mbstring.php
実装はこのようになります。
stream_filter_register('convert.mbstring.*','Stream_Filter_Mbstring');
$fp = fopen("example.csv", 'r');
stream_filter_append($handle,'convert.mbstring.encoding.SJIS-win:UTF-8');
while ($data = fgetcsv($fp, 10000)) {
// もうUTF8になってるからそのままDBにinsertとかupdateとかできるよ
}
クラス1つなので、コピペしておこうかと思ったんですが(PEAR久し振りだからちょっとだるい)、折角composerでライブラリ管理しているので、composerからopenpear経由で管理するようにしましたが、これがはまりました…。
Composerでライブラリの追加
コレを実行。
composer config repositories.0 "pear" "http://openpear.org"
composer require "pear-openpear.org/Stream_Filter_Mbstring" "0.0.7"
…といけば、万々歳だったのですが、ハマりました。エラーメッセージはこんなで、どうやらhttpsでロードしたほうがいいよといっているようです。
エラーでた
$ composer require "pear-openpear.org/Stream_Filter_Mbstring" "0.0.7"
./composer.json has been updated
Loading composer repositories with package information
Initializing PEAR repository http://openpear.org
PEAR repository from http://openpear.org could not be loaded. Your configuration does not allow connections to http://openpear.org/channel.xml. See https://getcomposer.org/doc/06-config.md#secure-http for details.
Updating dependencies (including require-dev)
Your requirements could not be resolved to an installable set of packages.
Problem 1
- The requested package pear-openpear.org/stream_filter_mbstring could not be found in any version, there may be a typo in the package name.
Potential causes:
- A typo in the package name
- The package is not available in a stable-enough version according to your minimum-stability setting
see <https://getcomposer.org/doc/04-schema.md#minimum-stability> for more details.
Read <https://getcomposer.org/doc/articles/troubleshooting.md> for further common problems.
Installation failed, reverting ./composer.json to its original content.
そこで、repositories
を https://openpear.org
としても、チャンネルファイルのリンクが http://openpear.org/channel.xml
となっていて、http://
のままなので、同じエラーが出ます。
エラー解決した
composerの設定でsecure-httpをoffにすることで解決しました。
あまり良くないけどしょうがないかなって。
composer config secure-http false
こレを実行した後、composer requireとかやると、ちゃんとインストールされます。