Blogブログ

Laravelでcsv機能を実装した時にハマったこと

※本記事ではcsvのimport機能自体については触れていませんのでご注意ください。

こんにちは。エンジニアの砂町です。

以前Laravelでcsvのimport機能を作成しました。
受託開発で企業様の社内のシステムを 0=>1 で作っているとよく出てくる機能なのかなと思います。

今ユーザーの情報などはexcelとかで管理してるので、それを読み込んでマスターとしてシステムに登録してしまおうってやつです。
膨大なデータ一件一件手で入力なんてしてられないもんですね、、

ITって便利だな〜〜

背景

ということで、苦戦しつつも何とか機能実装をして、自分の環境でテストなどをして確認を終えました。
最後に頂いたデータを入れようとしてみると、なぜかエラーが返ってくる。
あれ??
エラーが出た行のcsvの内容確認したり、デバックでデータの内容を出力してみたりするも、データはあってるっぽい。
試しに同じデータを自分で作ってimportしてみると正常に動いている。

え、なんなんこれ、意味わからん、、
ボーと出力した内容眺めていると、神様から御告げが、、

神様)同じ内容なのにlengthが異なているよ。。。

わ!なんで!
(神様教えてくれてありがとう。)

ていうことで調べてみると、BOMってやつが悪さをしていたらしい、、

デバック方法

上の話であるように、デバックで普通に文字を出力しただけではBOMが入っていたということはわかりません。
ただlengthが異なっていたので、そこで当たりはつけれるかもしれません。
内容を確認したい時は普通に変数を出力するのではなく下記のような形で、urlにエンコードしてあげると違いがわかります。

var_dump($value);
var_dump(urlencode($value));

ここで出力した内容の先頭にある「\xEF\xBB\xBF」がBOMの部分になります。

解決方法

デバックで確認できた「\xEF\xBB\xBF」の部分を下記のような感じで取り除いてあげるだけで終わりです。

$content = preg_replace('/^\xEF\xBB\xBF/', '', $content);

余談

で、動くようにはなったけど結局BOMって何なん?
というわけで下記Wikipedia様より一部抜粋

UnicodeがはじまったころはアメリカではASCII、ヨーロッパなどではISO-8859、日本ではShift_JISやEUC-JPが主流であり、使用されている符号化方式がUnicodeであることを明確に区別する必要があった。その方法として、先頭のデータにテキスト以外のデータを入れることが発案された。

出典:フリー百科事典『ウィキペディア(Wikipedia)』

なるほど、「使用されている符号化方式がUnicodeであることを明確に区別するため」に必要だったということですね。
BOMなんか全部なしでいいやんって思ってました。ごめんねBOM。

砂町

執筆者

Developer

砂町