
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