file_exists() is_file() 速度比較

ファイルの存在確認をするときに使う関数 file_exists() 、 is_file() の速度を比較するため簡単なコードを書いてテスト。
<?php
$time_start = microtime(true);//計測開始
$img='img/hoge.png';
for($i=0; $i<100000;++$i){//10万回繰り返す
file_exists($img);
}
$time = microtime(true) - $time_start; echo "{$time} 秒";
//計測結果
$time_start = microtime(true);//計測開始
$img='img/hoge.png';
for($i=0; $i<100000;++$i){
is_file($img);
}
$time = microtime(true) - $time_start; echo "{$time} 秒";
//計測結果

//0.37799286842346 秒 0.038822174072266 秒 さくらのレンタルサーバライト
is_file() のほうが、10倍速いという結果がでました。

テストしたコードが単純すぎてキャッシュを確認しているだけだとしても…。
速度差が10倍…なら is_file() で構わないところは is_file() を使ったほうが。

動作の違いは…。
$img='img/';
var_dump(is_file($img));//bool(false)
var_dump(file_exists($img));//bool(true)
$img='img/hoge.png';
var_dump(is_file($img));//bool(true)
var_dump(file_exists($img));//bool(true)
file_exists()は、ディレクトリしかなくても bool(true) を返します。 is_file() では bool(false) になります。

POTI-boardで使用されている file_exists() の該当箇所をしらべてみると…。
ディレクトリの確認をしているかもしれない箇所はほとんどなく逆にディレクトリしかなくても bool(true) では意図した動作にならないところに file_exists() が使用されている事がわかりました。

POTI-boardは一言書いて投稿するだけでもすべてのログを解析してHTMLファイルに書き出します。
そのためログが肥大化すると処理速度が遅くなってしまうのですが…さらに投稿するたびにすべての画像ファイルにアニメファイルがあるかどうか確認しているのでそこに重い関数を使うと…。

投稿時にアニメファイルの存在確認を行う回数が一目でわかるようにdumpしてみました。

file_exists()をis_file()に

アニメファイルの存在確認を file_exists() から is_file() に書き換えたところ8秒かかっていた投稿処理時間が1秒に短縮。

運営している絵板は設置件数が多くログ保持件数が多いのに一番安いさくらのレンタルサーバ ライトのライトプランなので、遅くても仕方がないのかな?と思っていたのですがどうにか…。

この変更は、POTI-board改 v1.52.9 lot.190812に反映されました。
(最新版は v1.53.2 lot.190831)

POTI-board改のダウンロードはこちらから。

お絵かき掲示板はこちら。

phpのOpenSSL関数で暗号化 復号化

phpでpasswordを暗号化して復号化…。
password_hash()は暗号化ではなくハッシュ化なので元のpasswordに戻す事はできません。
ではどうしたら…。
PHPで文字列を暗号化 - Qiita
なんか複雑なコードが書いてある…。これは私には手におえない?
phpのマニュアルは…。

PHP: OpenSSL 関数 - Manual

PHP マニュアル 関数リファレンス 暗号 OpenSSL
目次が…。
という事でできてみればたったこれだけ…のコードに1時間以上…。
<?php
$pwd = 'hogefuga';
define('crypt_pass','VNCLiX9BaeuzfaR');//暗号鍵
define('crypt_method','aes-128-cbc');//method
define('crypt_iv','FpXe2VNEVwLhJa8a');//iv 16バイト
$pwd=openssl_encrypt ($pwd,crypt_method, crypt_pass, true, crypt_iv);//暗号化
$pwd=bin2hex($pwd);//16進数に
var_dump($pwd);
//string(32) "9427c68b3e6ba3468c773d1b8f54359a"
$pwd=hex2bin($pwd);//バイナリに
$pwd=openssl_decrypt($pwd,crypt_method, crypt_pass, true, crypt_iv);
var_dump($pwd);// string(8) "hogefuga"
ivは半角16文字(16バイト)で。
暗号鍵は暗号化復号化のための固有の文字列。
methodは aes-128-cbc。

暗号化したpasswordをバイナリから16進数に変換したものをGETで取得して、16進数をバイナリに戻して復号化。

続きから描く時にペイント画面に入るpasswordを暗号化する事ができました。

この変更は、POTI-board改 v1.53.0 lot.190823 に反映されました。

お絵かき掲示板はこちら。

$_POST $_GET から filter_input()へ

POTI-boardの$delに不正な値が入らないようにする: STP^3
でこう書きました。
$del = ( isset($_POST["del"]) === true ) ? ($_POST["del"]): "";

if(is_array($del)){
$countdel=count($del);
for($i = 0; $i < $countdel; $i++){
if(!ctype_digit($del[$i])){//数字のみ
$del="";
}
}
}
else{
$del="";
}
数字しか入らなくする工夫だったのですが…。
foreachを使ったほうが的確だったかも。そして…。
$_GET, $_POST じゃなくて filter_input 使えとのこと - Qiita
$del = filter_input(INPUT_POST,'del',FILTER_VALIDATE_INT,FILTER_REQUIRE_ARRAY);//$del は配列
配列にもfilter_input() を使う事ができるので FILTER_VALIDATE_INT で整数以外入らなくなりました。とてもスマートです。

$_POST $_GET から filter_input()へ
$anime = filter_input(INPUT_POST, 'anime',FILTER_VALIDATE_BOOLEAN);
bool型以外受け付けないので、入る値はtrueまたはfalseのみ。
取得する値がないときは変数にNULLがセットされるので未定義になりません。
【PHP入門講座】 NULLと未定義の違い - Qiita
$_POST[]は書き換える事ができるので意図しない値が入る可能性…。スクリプトの先頭で取得するだけなら問題ないのかもしれませんが途中で他の値を代入しているスクリプトも存在していて…httpからPOSTされたデータなのか、代入して書き換えられた値なのかわからなくなるケースもあるようです。
PHP - スーパーグローバル変数に直接アクセスしない方がいい理由|teratail

filter_input()を使った場合、スーパーグローバルの$_GETや$_POSTではなく、本当にHTTPで投げられた値を元に結果を返します。
この変更はPOTI-board改 v1.51.9 lot.190612に反映されました。
注意:2019年8月29日現在の最新版は POTI-board改 v1.53.1 lot.190827です。

POTI-board改の最新版のダウンロードはこちらから。
お絵かき掲示板はこちら。