背景
特定のファイルをcleanするコードを書きたくて
$result = app('files')->put($this->pathFromInput('clean'), '');
$result_str = $result ? "success" : "failure";
\Log::info("{$this->pathFromInput('clean')} cleaned: {$result_str}.");
みたいなコードを書いていたんですけど、ファイルの中身が消されてるのに結果がFalseで返ってきてておかしいなって思いました。
調査
なのでLaravelのコードをのぞいてみました。
https://github.com/laravel/framework/blob/7.x/src/Illuminate/Filesystem/Filesystem.php#L133-L136
public function put($path, $contents, $lock = false)
{
return file_put_contents($path, $contents, $lock ? LOCK_EX : 0);
}
なんだ単にfile_put_contents
コールしてるだけなのね。PHPの方を調べてみよう。
https://www.php.net/manual/ja/function.file-put-contents.php#refsect1-function.file-put-contents-returnvalues
この関数はファイルに書き込まれたバイト数を返します。 あるいは失敗した場合には FALSE を返します。
警告
この関数は論理値 FALSE を返す可能性がありますが、FALSE として評価される値を返す可能性もあります。 詳細については 論理値の セクションを参照してください。この関数の返り値を調べるには ===演算子 を 使用してください。
...
0バイト書き込めば0が返ってくるから実質FALSEになるので$result===0
と$result===''
で使い分けるということのようです。
まとめ
建前
PHPはこういった想定外の落とし穴があるので注意しましょう。他の言語だとこういうのあんまりないと思います…。
本心
は??????マジで?????なにこのPHPの仕様クソすぎない????なんのためにboolがあるの????言語として破綻してない????酒飲みながら考えたみたいな仕様だな????
Java, C#, Objective C, Swift, Kotlin, JavaScript, Ruby, Python, Golang と触れてきたけどここまで書きにくい言語は初めてなので正直叫びたい。
PHP大っ嫌いだー!