文件
xionggeshop/addons/shopro/cleanup_missing_attachments.php

101 行
3.0 KiB
PHP

此文件含有模棱两可的 Unicode 字符

此文件含有可能会与其他字符混淆的 Unicode 字符。 如果您是想特意这样的,可以安全地忽略该警告。 使用 Escape 按钮显示他们。

<?php
/**
* 清理图片空间中「数据库有记录但物理文件不存在」的附件
*
* 用法(在项目根目录执行):
* php addons/shopro/cleanup_missing_attachments.php --dry-run # 仅预览
* php addons/shopro/cleanup_missing_attachments.php # 硬删除无效记录
* php addons/shopro/cleanup_missing_attachments.php --soft # 移入回收站(is_del=1)
*/
if (PHP_SAPI !== 'cli') {
http_response_code(403);
exit("请通过命令行运行:php addons/shopro/cleanup_missing_attachments.php [--dry-run] [--soft]\n");
}
define('APP_PATH', __DIR__ . '/../../application/');
define('ROOT_PATH', __DIR__ . '/../../');
if (!is_file(APP_PATH . 'admin/command/Install/install.lock')) {
fwrite(STDERR, "项目未安装,无法执行。\n");
exit(1);
}
require ROOT_PATH . 'thinkphp/base.php';
\think\App::initCommon();
use think\Db;
$argv = $GLOBALS['argv'] ?? [];
$dryRun = in_array('--dry-run', $argv, true);
$softDelete = in_array('--soft', $argv, true);
$publicPath = rtrim(ROOT_PATH, '/\\') . DIRECTORY_SEPARATOR . 'public';
$batchSize = 500;
$lastId = 0;
$checked = 0;
$missing = 0;
$now = time();
echo "扫描目录:{$publicPath}\n";
echo '模式:' . ($dryRun ? '预览(不写入)' : ($softDelete ? '软删除(回收站)' : '硬删除(直接删记录)')) . "\n\n";
while (true) {
$rows = Db::name('attachment')
->where('id', '>', $lastId)
->where('storage', 'local')
->order('id asc')
->limit($batchSize)
->field('id,url,filename,is_del,mimetype')
->select();
if (empty($rows)) {
break;
}
foreach ($rows as $row) {
$row = is_array($row) ? $row : $row->toArray();
$lastId = (int)$row['id'];
$checked++;
$url = trim((string)($row['url'] ?? ''));
if ($url === '') {
$exists = false;
} elseif (preg_match('#^https?://#i', $url)) {
// 外链不做本地存在性检查
continue;
} else {
$relative = '/' . ltrim(str_replace('\\', '/', $url), '/');
$file = $publicPath . str_replace('/', DIRECTORY_SEPARATOR, $relative);
$exists = is_file($file);
}
if ($exists) {
continue;
}
$missing++;
$name = $row['filename'] ?? '';
$delFlag = !empty($row['is_del']) ? ' [已在回收站]' : '';
echo "[缺失] id={$row['id']} url={$url} filename={$name}{$delFlag}\n";
if ($dryRun) {
continue;
}
if ($softDelete) {
Db::name('attachment')->where('id', $row['id'])->update([
'is_del' => 1,
'updatetime' => $now,
]);
} else {
Db::name('attachment')->where('id', $row['id'])->delete();
}
}
}
echo "\n完成:共检查 {$checked} 条本地附件,发现缺失 {$missing} 条";
echo $dryRun ? '(预览,未修改数据库)' : '(已清理)';
echo "\n";