aiblog/app/Http/Controllers/Api/PostController.php
2024-11-17 11:30:01 +08:00

139 lines
No EOL
4.5 KiB
PHP

<?php
declare(strict_types=1);
namespace App\Http\Controllers\Api;
use App\Http\Controllers\Controller;
use App\Models\Post;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use App\Http\Requests\Post\ListPostRequest;
use App\Http\Resources\PaginatedResource;
class PostController extends Controller
{
public function index(ListPostRequest $request): JsonResponse
{
$validated = $request->validated();
$perPage = min($request->input('per_page', 10), 100);
$sortBy = $request->input('sort_by', 'created_at');
$sortOrder = $request->input('sort_order', 'desc');
$allowedSortFields = ['created_at', 'title', 'views'];
$sortBy = in_array($sortBy, $allowedSortFields) ? $sortBy : 'created_at';
$sortOrder = in_array($sortOrder, ['asc', 'desc']) ? $sortOrder : 'desc';
$query = Post::with(['author:id,name', 'category:id,name'])
->when($request->authorId, fn($q) => $q->where('author_id', $request->authorId))
->when($request->category, fn($q) => $q->whereHas('category', fn($q) =>
$q->where('name', $request->category)
))
->when($request->search, fn($q) => $q->where(fn($q) =>
$q->where('title', 'like', "%{$request->search}%")
->orWhere('content', 'like', "%{$request->search}%")
));
$query->orderBy($sortBy, $sortOrder);
$posts = $query->paginate($perPage);
return response()->success([
'posts' => new PaginatedResource($posts)
]);
}
public function show(Request $request, Post $post): JsonResponse
{
$this->postViewService->recordView($post, $request->ip());
$post->load(['author:id,name', 'comments.author:id,name']);
return response()->json([
'post' => [
'id' => $post->id,
'title' => $post->title,
'content' => $post->content,
'author' => $post->author,
'comments' => $post->comments->map(fn($comment) => [
'id' => $comment->id,
'content' => $comment->content,
'author' => $comment->author,
'created_at' => $comment->created_at,
]),
'created_at' => $post->created_at,
]
]);
}
public function store(Request $request): JsonResponse
{
$validated = $request->validate([
'title' => 'required|string|max:255',
'content' => 'required|string',
'category_id' => 'nullable|exists:categories,id',
'summary' => 'nullable|string|max:500',
]);
$post = $request->user()->posts()->create($validated);
return response()->json([
'message' => 'Post created successfully',
'post' => [
'id' => $post->id,
'title' => $post->title,
'content' => $post->content,
'author' => [
'id' => $request->user()->id,
'name' => $request->user()->name,
],
'created_at' => $post->created_at,
]
]);
}
public function update(Request $request, Post $post): JsonResponse
{
$this->authorize('update', $post);
$validated = $request->validate([
'title' => 'sometimes|string|max:255',
'content' => 'sometimes|string',
'category_id' => 'nullable|exists:categories,id',
'summary' => 'nullable|string|max:500',
]);
$post->update($validated);
return response()->json([
'message' => 'Post updated successfully',
'post' => [
'id' => $post->id,
'title' => $post->title,
'content' => $post->content,
'author' => [
'id' => $post->author->id,
'name' => $post->author->name,
],
'updated_at' => $post->updated_at,
]
]);
}
public function destroy(Post $post): JsonResponse
{
$this->authorize('delete', $post);
$post->delete();
return response()->json([
'message' => 'Post deleted successfully'
]);
}
public function popular(Request $request): JsonResponse
{
return response()->json([
'data' => $this->postViewService->getPopularPosts(),
]);
}
}