PHP はよくウェブサイトの構築に使われ、ユーザーがアップロードしたファイルを保存、削除することもしばしばあります。アップロードしたファイルを保存する時、よく次の様にランダム文字列なり日時なりで何がしかのディレクトリを保存場所のルートディレクトリとファイルの間に噛ませます。これをするとファイルの名前を保ったまま保存しても同名ファイルが衝突しなくなり便利です。
<?php
<?php
// ランダム文字列例
$randomStr = substr(str_replace(['=', '+', '/'], '', base64_encode(random_bytes(12))), 0, 4);
file_put_contents("/ファイル保存用ディレクトリ/" . $randomStr . "/" . $アップロードされたファイルの名前, $アップロードされたファイルの中身);
// 日時例
$datetime = (new DateTime)->format('Y/m/d/H/i/s/u');
file_put_contents("/ファイル保存用ディレクトリ/" . $datetime . "/" . $アップロードされたファイルの名前, $アップロードされたファイルの中身);
このディレクトリを挟む仕組みはユーザーがファイル名について気にしなくなる点で良いのですが、単にファイルを削除する時に比べて、ディレクトリの削除が手間になります。一応削除しない方法もできますがファイルシステム側から何かをする時にダミー的なディレクトリが増えることで色々と面倒になります。ディレクトリが空の場合のみに削除するコードを紹介します。コードは次です。
<?php
$deleteTgtFilePath = '削除対象ファイルのフルパス';
// ファイルを削除
if (is_file($deleteTgtFilePath)) {
unlink($deleteTgtFilePath);
}
// 削除対象のファイルが入っていたとされるディレクトリのパスの宛先がディレクトリであり、
// そのディレクトリの中を glob で走査して何もみつからないならば
if (is_dir(dirname($deleteTgtFilePath)) && count(glob(dirname($deleteTgtFilePath).'/*')) === 0) {
// ディレクトリを削除
rmdir(dirname($fullPath));
}
割とシンプルに済みます。これをするだけでファイルシステムの中をきれいに保てます。何階層かのディレクトリをまとめて削除する目的ならば次の様にしてさかのぼることもできます。最初の例の様に決まった深さだけ削除対象のディレクトリがありうるとわかっているならば、再帰を書かなくても関数を何度か呼ぶだけで適切な分だけ削除を試みることができます。
<?php
/** 渡されたディレクトリの中が空ならばディレクトリを削除する */
function rmdirIfEmpty(string $deleteTgtDir): void
{
if(is_dir($deleteTgtDir) && count(glob($deleteTgtDir . '/*')) === 0) {
// ディレクトリを削除
rmdir($deleteTgtDir);
}
}
$deleteTgtFilePath = '削除対象ファイルのフルパス';
// dirname 関数で得た今参照している対象の入っているディレクトリを得る、
// ディレクトリの削除を試みる、
// dirname 関数で得た今参照している対象の入っているディレクトリを得る、
// と繰り返すことで浅い方向に向かってならば何階層も削除を試みることができます。
rmdirIfEmpty($deleteTgtDir = dirname($deleteTgtFilePath));
rmdirIfEmpty($deleteTgtDir = dirname($deleteTgtDir));
rmdirIfEmpty($deleteTgtDir = dirname($deleteTgtDir));
rmdirIfEmpty($deleteTgtDir = dirname($deleteTgtDir));