Laravel 受け取ったファイルの文字コードを確実に判定する方法

phpのexec関数を使うことにより、サーバー上でnkfコマンドを実行するやり方を提唱する。

nfkはファイルの文字コードを調べたり、任意の文字コードに変換したりできるlinuxのコマンド。

phpに元からある関数でも判定できるとされているが、精度がよくない。
それなら、サーバーの中でコマンドを叩いて確認しちゃおうぜ!って案。

nkfコマンドをインストール

ubuntuのコンテナの例。

サーバーでコマンドを実行する。

もしDockerならコンテナに入る。

ほんで、

apt update

apt-get install nkf

を実行。

nkf -vを叩いてこうなったら成功。

root@d037b34a02d9:/work/public# nkf -v
Network Kanji Filter Version 2.1.5 (2018-12-15)
Copyright (C) 1987, FUJITSU LTD. (I.Ichikawa).
Copyright (C) 1996-2018, The nkf Project.

apt updateが必要な理由は下記の外部サイトに記載あり。

UbuntuでUnable to locate packageのエラー解決法


そしたら、

一旦サーバー上のどこかしらにCSVファイルを置く。

サーバー上(Dockerならコンテナ内のコマンドライン)で、そのファイルの文字コードを調べる。

nkf -g /work/public/storage/hoge.csv

ちなみに日本語が1文字も含まれていないと、ASCII扱いになる!!

csvファイルのヘッダー(1行目)とかにでもいいので、1文字でも日本語(全角文字)が含まれていればちゃんとutf-8と判定ができる。

exec関数でnkfコマンドサーバー上で実行

execコマンドは、サーバー上で任意のコマンドを実行して、その結果を返してくれる便利な関数。

<?php
//CsvController.php
namespace App\Http\Controllers;

use Illuminate\Http\Request;

use Illuminate\Support\Facades\Storage;//必須!!!!!!!

class CsvController extends Controller
{
    public function judgeCharacterCode(Request $request){
        $name = substr(bin2hex(random_bytes(8)), 0, 8); //ランダムなファイル名を生成

        $directory = 'public/csv'; //保存先

        $request->file->storeAs($directory,$name.'.csv'); //アップロード

        $charactor = exec('nkf -g /work/public/storage/csv/'.$name.'.csv');

        Storage::delete($directory.'/'.$name.'.csv');//アップロードしたファイルを削除

        //文字コードをリターン
        return  $charactor;

    }
}

csvファイルを1回storageにアップロードしないといけない。

でもcsvファイル自体を保存しておく必要がなければ、文字コード判定後に削除する。(上記の例では消している)

「UTF-8」とか「Shif-JIS」とかの結果が返ってくる。

自分は「関数の実行結果がUTF-8でなければ、フロント側でブロックする」みたいな使い方をしている。

サーバー上でnkf コマンドを実行委する指示をLaravel側からできるということは、やろうと思えば文字コードの変換もできることになる。

本番環境に個別インストールは必要か

Docker環境でも、そのままデプロイすると必要になっちゃう。

その場合、execの実行結果はnullっぽい感じになる。

dockerfileにインストールのコマンドを書いてあげよう。

apt-get install nkf && \

をDockerfileに追記する。

自分の場合はこんな風になった。

infra\php\Dockerfile

FROM php:8.0-fpm-buster
SHELL ["/bin/bash", "-oeux", "pipefail", "-c"]

ENV COMPOSER_ALLOW_SUPERUSER=1 \
    COMPOSER_HOME=/composer

COPY --from=composer:2.0 /usr/bin/composer /usr/bin/composer

RUN apt-get update && \
    apt-get -y install git unzip libzip-dev libicu-dev libonig-dev libfreetype6-dev libjpeg62-turbo-dev libpng-dev && \
    apt-get clean && \
    apt-get install nkf && \
    rm -rf /var/lib/apt/lists/* && \
    docker-php-ext-configure gd --with-freetype --with-jpeg && \
    docker-php-ext-install -j$(nproc) gd && \
    docker-php-ext-install intl pdo_mysql zip bcmath

COPY ./php.ini /usr/local/etc/php/php.ini

WORKDIR /work

git cloneして試してみたら手動でインストール不要になってた!

なぜ文字コードの判定が必要なのか

  • csvファイルからデータベースに一括で情報を登録したい
  • でもshift-jisのファイルを投稿されたら文字化けするから阻止したい

みたいなときに使えるわけやな。

特にCSVを扱うライブラリ「Laravel Excel」なんかを併用して使うときには、みんなブチ当たる問題と思われる。

phpの関数mb_convert_encodingとかで判定する方法もあるけど、精度が甘くて使い物にならなかった。

下記の外部サイトのやり方も試したがうまく行かず・・・

http://php.o0o0.jp/article/php-encoding

というわけで、精度がよさげなlinuxのコマンドnkfコマンドを力業で実行した。

今回の環境

  • php8
  • Laravel8
  • Docker
  • ubuntu
無制限に質問可能なプログラミングスクール!

万が一転職できない場合は、転職保障全額返金できるコースもあり!!

無制限のメンター質問対応

 

DMMウェブキャンプでプログラミングを学習しませんか?

独学より成長スピードをブーストさせましょう!

 

まずは無料相談から!

おすすめの記事