50 lines
No EOL
1.3 KiB
PHP
50 lines
No EOL
1.3 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace App\Services;
|
|
|
|
use App\Models\Post;
|
|
use Illuminate\Support\Facades\Cache;
|
|
use Illuminate\Support\Facades\DB;
|
|
|
|
class PostViewService
|
|
{
|
|
protected CacheService $cacheService;
|
|
|
|
public function __construct(CacheService $cacheService)
|
|
{
|
|
$this->cacheService = $cacheService;
|
|
}
|
|
|
|
public function recordView(Post $post, string $visitorId): void
|
|
{
|
|
$cacheKey = "post:{$post->id}:visitor:{$visitorId}";
|
|
|
|
if (!Cache::has($cacheKey)) {
|
|
DB::transaction(function () use ($post) {
|
|
$post->increment('views');
|
|
});
|
|
|
|
// 设置24小时内同一访客不重复计数
|
|
Cache::put($cacheKey, true, now()->addHours(24));
|
|
}
|
|
}
|
|
|
|
public function getPopularPosts(int $limit = 10): array
|
|
{
|
|
return $this->cacheService
|
|
->tags(['posts', 'popular'])
|
|
->remember('posts:popular', function () use ($limit) {
|
|
return Post::orderByDesc('views')
|
|
->limit($limit)
|
|
->get()
|
|
->map(fn($post) => [
|
|
'id' => $post->id,
|
|
'title' => $post->title,
|
|
'views' => $post->views,
|
|
])
|
|
->toArray();
|
|
});
|
|
}
|
|
}
|