在php7.1 下使用WSTMALL出现一下问题,关于php的文件操作 WSTMALL的处理方式如下
function WSTDelDir($dirpath)
{
$dh = opendir($dirpath);
while (($file = readdir($dh))!==false) { //=====>C
if ($file != "." && $file != "..") {
$fullpath = $dirpath . "/" . $file;
if (!is_dir($fullpath)) {
unlink($fullpath);
} else {
WSTDelDir($fullpath); //=======>A
rmdir($fullpath);
}
}
}
closedir($dh);//=========>B
$isEmpty = 1;
$dh = opendir($dirpath);
while (($file = readdir($dh)) != false) {
if ($file != "." && $file != "..") {
$isEmpty = 0;
break;
}
}
return $isEmpty;
}
我调试了一下发现文件夹正常删除,但是 最后总会遇到一个TEMP文件夹内有文件。
所以个人感觉WSTMALL的删除有问题。
通过个人跟踪发现 标记为A处的命令并没有执行第二次,只执行到第一处就结束了。也就是说。这个方法没有深度递归。
于是我用了另一个opensns的实现
function WSTDelDir($dirname)
{
if (!file_exists($dirname)) {
return 0;
}
if (is_file($dirname) || is_link($dirname)) {
return unlink($dirname);
}
$dir = dir($dirname);
if($dir){
while (false !== $entry = $dir->read()) {
if ($entry == '.' || $entry == '..') {
continue;
}
WSTDelDir($dirname . DIRECTORY_SEPARATOR . $entry);
}
}
$dir->close();
return rmdir($dirname);
}
对比之后发现原来是原先的实现有问题。
关键就在于B标记之后.
1. WSTMALL的写法有读取了一遍文件夹。这个是有问题的。原因在于当前进程虽然在之前成功删除了文件夹,但是并没有保证其他进程不会生成缓存文件。所以WSTMALL的失败就在此处。
2. 另一点就是OPENSNS的处理方式,成功的删除了所有缓存文件,而 WSTMALL无法成功处理也在于B标记之后的数据,他提前返回了。并没有循环完毕所有的目录。
3. 最后说一下
关于在PHP7.1正式版下为什么WSTMALL的清理方法不执行了。
原因是PHP7.1 修正一处bug 。[x] Fixed bug #72667 (opendir() with ftp:// attempts to open data stream for non-existent directories).
这导致opendir()打开一个不存在目录返回的是null而不是false