ClearAppCache.php 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081
  1. <?php
  2. namespace App\Console\Commands;
  3. use Illuminate\Console\Command;
  4. use Illuminate\Support\Facades\Cache;
  5. class ClearAppCache extends Command
  6. {
  7. /**
  8. * 名字里不用 cache:clear / cache:forget —— 那两个是 Laravel 内置命令,会撞。
  9. *
  10. * @var string
  11. */
  12. protected $signature = 'cache:app.clear {name? : 缓存项名称,不传则列出可清理的项} {--all : 清理全部}';
  13. /**
  14. * @var string
  15. */
  16. protected $description = '清理由应用代码显式写入的缓存(如书目清单),不影响框架自身的缓存';
  17. /**
  18. * 可清理的缓存项:名称 => 实际的 cache key 列表。
  19. *
  20. * 新增带缓存的接口时在这里登记一行,命令与提示会自动跟上。
  21. *
  22. * @var array<string, array{keys: string[], desc: string}>
  23. */
  24. private const CACHES = [
  25. 'book-titles' => [
  26. 'keys' => ['book-titles/with-tags'],
  27. 'desc' => '书目清单(含 toc 与 tag),TTL 24 小时',
  28. ],
  29. ];
  30. public function handle(): int
  31. {
  32. $name = $this->argument('name');
  33. if (! $name && ! $this->option('all')) {
  34. $this->line('可清理的缓存项:');
  35. foreach (self::CACHES as $key => $item) {
  36. $cached = collect($item['keys'])->filter(fn ($k) => Cache::has($k))->count();
  37. $state = $cached > 0 ? "已缓存 {$cached}/".count($item['keys']) : '未缓存';
  38. $this->line(sprintf(' %-14s %-34s [%s]', $key, $item['desc'], $state));
  39. }
  40. $this->newLine();
  41. $this->line('用法:php artisan cache:app.clear <名称> 或 --all');
  42. return self::SUCCESS;
  43. }
  44. if ($name && ! isset(self::CACHES[$name])) {
  45. $this->error("未知的缓存项:{$name}");
  46. $this->line('可选:'.implode(' / ', array_keys(self::CACHES)));
  47. return self::FAILURE;
  48. }
  49. $targets = $name ? [$name => self::CACHES[$name]] : self::CACHES;
  50. $cleared = 0;
  51. foreach ($targets as $key => $item) {
  52. foreach ($item['keys'] as $cacheKey) {
  53. // forget 对不存在的 key 也返回 true,所以先问一次才能如实报告清了几条
  54. $existed = Cache::has($cacheKey);
  55. Cache::forget($cacheKey);
  56. if ($existed) {
  57. $cleared++;
  58. $this->info("已清理 {$key}:{$cacheKey}");
  59. } else {
  60. $this->line("跳过 {$key}:{$cacheKey}(本来就没有缓存)");
  61. }
  62. }
  63. }
  64. $this->newLine();
  65. $this->info("共清理 {$cleared} 条缓存。下次请求会重新构建。");
  66. return self::SUCCESS;
  67. }
  68. }