From 28c7a317e5c759aca7f217462c3fb1718b810eb6 Mon Sep 17 00:00:00 2001 From: parsa aghaei Date: Tue, 23 Jun 2026 18:09:15 +0330 Subject: [PATCH] 1.2: restructure controllers to Api/ prefix and update routes --- .../Api/Blog/CategoryController.php | 109 +++++++++++++ .../{ => Api}/Blog/HomeController.php | 13 +- .../{ => Api}/Blog/PostController.php | 25 +-- .../{ => Api}/Blog/TagController.php | 10 +- .../{ => Api}/Website/AboutMeController.php | 24 ++- .../{ => Api}/Website/ProjectController.php | 10 +- .../{ => Api}/Website/ServiceController.php | 10 +- .../Controllers/Blog/CategoryController.php | 144 ------------------ app/Http/Resources/User.php | 25 --- app/Http/Resources/UserCollection.php | 19 --- routes/api.php | 19 +-- 11 files changed, 137 insertions(+), 271 deletions(-) create mode 100644 app/Http/Controllers/Api/Blog/CategoryController.php rename app/Http/Controllers/{ => Api}/Blog/HomeController.php (70%) rename app/Http/Controllers/{ => Api}/Blog/PostController.php (60%) rename app/Http/Controllers/{ => Api}/Blog/TagController.php (81%) rename app/Http/Controllers/{ => Api}/Website/AboutMeController.php (66%) rename app/Http/Controllers/{ => Api}/Website/ProjectController.php (91%) rename app/Http/Controllers/{ => Api}/Website/ServiceController.php (77%) delete mode 100644 app/Http/Controllers/Blog/CategoryController.php delete mode 100644 app/Http/Resources/User.php delete mode 100644 app/Http/Resources/UserCollection.php diff --git a/app/Http/Controllers/Api/Blog/CategoryController.php b/app/Http/Controllers/Api/Blog/CategoryController.php new file mode 100644 index 0000000..2d5641e --- /dev/null +++ b/app/Http/Controllers/Api/Blog/CategoryController.php @@ -0,0 +1,109 @@ +input('filter'); + $sortBy = $request->input('sort_by', 'created_at'); + $sortDirection = $request->input('sort_direction', 'desc'); + $perPage = $request->input('per_page', 10); + + $query = Category::with('posts'); + + if (!empty($filter)) { + $query->where('name', 'like', '%' . $filter . '%'); + } + + $query->orderBy($sortBy, $sortDirection); + + $categories = $query->paginate($perPage); + + return CategoryResource::collection($categories); + } + + public function show($id) + { + $category = Category::with('posts')->findOrFail($id); + return new CategoryResource($category); + } + + public function getCategoryWithPosts(Request $request, $slug) + { + $category = Category::where('slug', $slug)->first(); + + if (!$category) { + return response()->json([ + 'message' => 'Category not found.' + ], 404); + } + + $perPage = $request->input('per_page', 10); + $filter = $request->input('filter'); + $sortBy = $request->input('sort_by', 'published_at'); + $sortDirection = $request->input('sort_direction', 'desc'); + + $postsQuery = $category->posts()->with(['category', 'tags', 'author']); + + if (!empty($filter)) { + $postsQuery->where('title', 'like', '%' . $filter . '%'); + } + + $postsQuery->orderBy($sortBy, $sortDirection); + + $posts = $postsQuery->paginate($perPage); + + $meta = [ + 'total' => $posts->total(), + 'per_page' => $posts->perPage(), + 'current_page' => $posts->currentPage(), + 'last_page' => $posts->lastPage(), + 'from' => $posts->firstItem(), + 'to' => $posts->lastItem(), + ]; + + $links = [ + 'first' => $posts->url(1), + 'last' => $posts->url($posts->lastPage()), + 'prev' => $posts->previousPageUrl(), + 'next' => $posts->nextPageUrl(), + ]; + + return response()->json([ + 'category' => new CategoryResource($category), + 'posts' => PostResource::collection($posts), + 'meta' => $meta, + 'links' => $links, + ], 200); + } + + public function store(StoreCategoryRequest $request) + { + $category = Category::create($request->validated()); + return new CategoryResource($category); + } + + public function update(UpdateCategoryRequest $request, $id) + { + $category = Category::findOrFail($id); + $category->update($request->validated()); + return new CategoryResource($category); + } + + public function destroy($id) + { + $category = Category::findOrFail($id); + $category->delete(); + return response()->json(['message' => 'Category deleted successfully'], 200); + } +} diff --git a/app/Http/Controllers/Blog/HomeController.php b/app/Http/Controllers/Api/Blog/HomeController.php similarity index 70% rename from app/Http/Controllers/Blog/HomeController.php rename to app/Http/Controllers/Api/Blog/HomeController.php index d78ff7e..a8cd57d 100644 --- a/app/Http/Controllers/Blog/HomeController.php +++ b/app/Http/Controllers/Api/Blog/HomeController.php @@ -1,47 +1,36 @@ orderBy('published_at', 'desc') ->take(5) ->get(); - // 2. 5 دسته‌بندی آخر $latestCategories = Category::orderBy('created_at', 'desc') ->take(5) ->get(); - // 3. 5 پست با بیشترین بازدید $mostViewedPosts = Post::with(['category', 'tags', 'author']) ->orderBy('views', 'desc') ->take(5) ->get(); - // 4. 4 پست تصادفی $randomPosts = Post::with(['category', 'tags', 'author']) ->inRandomOrder() ->take(4) ->get(); - // بازگشت به صورت JSON با استفاده از منابع (Resources) return response()->json([ 'latest_posts' => PostResource::collection($latestPosts), 'latest_categories' => CategoryResource::collection($latestCategories), diff --git a/app/Http/Controllers/Blog/PostController.php b/app/Http/Controllers/Api/Blog/PostController.php similarity index 60% rename from app/Http/Controllers/Blog/PostController.php rename to app/Http/Controllers/Api/Blog/PostController.php index fcb53c3..87cbe05 100644 --- a/app/Http/Controllers/Blog/PostController.php +++ b/app/Http/Controllers/Api/Blog/PostController.php @@ -1,6 +1,6 @@ only(['category', 'tag', 'search', 'author', 'published']); - // دریافت پارامترهای مرتب‌سازی از درخواست - $sortField = $request->get('sort_field', 'published_at'); // فیلد پیش‌فرض: published_at - $sortDirection = $request->get('sort_direction', 'desc'); // جهت پیش‌فرض: نزولی + $sortField = $request->get('sort_field', 'published_at'); + $sortDirection = $request->get('sort_direction', 'desc'); - // دریافت پارامترهای صفحه‌بندی از درخواست - $perPage = $request->get('per_page', 10); // تعداد آیتم‌ها در هر صفحه (پیش‌فرض: ۱۰) + $perPage = $request->get('per_page', 10); - // ساخت Query با اعمال فیلترها و مرتب‌سازی $query = Post::with(['category', 'tags', 'author']) ->filter($filters) ->sort($sortField, $sortDirection); - // اعمال صفحه‌بندی $posts = $query->paginate($perPage); - // بازگشت نتایج به صورت JSON با استفاده از Resource return PostResource::collection($posts); } - // نمایش یک پست خاص public function show($slug) { - // یافتن پست بر اساس slug و بارگذاری روابط مرتبط $post = Post::with(['category', 'tags', 'author', 'relatedPosts.category', 'relatedPosts.tags', 'relatedPosts.author']) ->where('slug', $slug) - ->firstOrFail(); // در صورت عدم وجود پست، خطای 404 برمی‌گرداند + ->firstOrFail(); - // بازگشت پست و پست‌های مرتبط به صورت JSON با استفاده از منابع return response()->json([ 'post' => new PostResource($post), - 'related_posts' => PostResource::collection($post->relatedPosts->sortByDesc('published_at')->take(5)), // بازگشت ۵ پست مرتبط جدیدترین + 'related_posts' => PostResource::collection($post->relatedPosts->sortByDesc('published_at')->take(5)), ], 200); } - // ذخیره یک پست جدید public function store(StorePostRequest $request) { $post = Post::create($request->validated()); @@ -63,7 +52,6 @@ public function store(StorePostRequest $request) return new PostResource($post->load(['category', 'tags', 'author'])); } - // به‌روزرسانی یک پست خاص public function update(UpdatePostRequest $request, $id) { $post = Post::findOrFail($id); @@ -76,7 +64,6 @@ public function update(UpdatePostRequest $request, $id) return new PostResource($post->load(['category', 'tags', 'author'])); } - // حذف یک پست خاص public function destroy($id) { $post = Post::findOrFail($id); diff --git a/app/Http/Controllers/Blog/TagController.php b/app/Http/Controllers/Api/Blog/TagController.php similarity index 81% rename from app/Http/Controllers/Blog/TagController.php rename to app/Http/Controllers/Api/Blog/TagController.php index f45fbd1..60f71fd 100644 --- a/app/Http/Controllers/Blog/TagController.php +++ b/app/Http/Controllers/Api/Blog/TagController.php @@ -1,6 +1,6 @@ paginate(10); return TagResource::collection($tags); } - // نمایش یک تگ خاص public function show($id) { $tag = Tag::with('posts')->findOrFail($id); return new TagResource($tag); } - // ذخیره یک تگ جدید public function store(StoreTagRequest $request) { $tag = Tag::create($request->validated()); - return new TagResource($tag); } - // به‌روزرسانی یک تگ خاص public function update(UpdateTagRequest $request, $id) { $tag = Tag::findOrFail($id); $tag->update($request->validated()); - return new TagResource($tag); } - // حذف یک تگ خاص public function destroy($id) { $tag = Tag::findOrFail($id); $tag->posts()->detach(); $tag->delete(); - return response()->json(['message' => 'Tag deleted successfully'], 200); } } diff --git a/app/Http/Controllers/Website/AboutMeController.php b/app/Http/Controllers/Api/Website/AboutMeController.php similarity index 66% rename from app/Http/Controllers/Website/AboutMeController.php rename to app/Http/Controllers/Api/Website/AboutMeController.php index dc481a5..95e099c 100644 --- a/app/Http/Controllers/Website/AboutMeController.php +++ b/app/Http/Controllers/Api/Website/AboutMeController.php @@ -1,6 +1,6 @@ first(); // بارگذاری مهارت‌ها و ترجمه‌ها + $aboutMe = AboutMe::with('skills.translations')->first(); return response()->json($aboutMe); } @@ -40,33 +40,29 @@ public function destroy($id) return response()->json(null, 204); } - // متد جدید برای دریافت ترجمه بر اساس locale از کوکی public function getTranslation($id, $locale) { - // بارگذاری AboutMe با ترجمه‌های مربوط به locale و مهارت‌ها $aboutMe = AboutMe::with(['translations' => function ($query) use ($locale) { $query->where('locale', $locale); }, 'skills.translations' => function ($query) use ($locale) { $query->where('locale', $locale); }])->findOrFail($id); - // اگر ترجمه موجود نیست، می‌توانید ترجمه پیش‌فرض یا خطا را برگردانید if ($aboutMe->translations->isEmpty()) { return response()->json(['message' => 'Translation not found', 'locale' => $locale], 404); } - // ترکیب اطلاعات AboutMe و ترجمه - $translation = $aboutMe->translations->first(); // فقط یک ترجمه دریافت می‌کنیم + $translation = $aboutMe->translations->first(); $skills = $aboutMe->skills->map(function ($skill) use ($locale) { - $translation = $skill->getTranslation($locale); // گرفتن ترجمه برای هر مهارت + $translation = $skill->getTranslation($locale); return [ 'id' => $skill->id, - 'title' => $translation ? $translation->title : null, // عنوان از ترجمه - 'description' => $translation ? $translation->description : null, // توضیحات از ترجمه - 'image' => $skill->image, // تصویر - 'link' => $skill->link, // لینک - 'percentage' => $skill->percentage, // درصد + 'title' => $translation ? $translation->title : null, + 'description' => $translation ? $translation->description : null, + 'image' => $skill->image, + 'link' => $skill->link, + 'percentage' => $skill->percentage, ]; }); @@ -75,7 +71,7 @@ public function getTranslation($id, $locale) 'title' => $translation->title, 'description' => $translation->description, 'image' => $aboutMe->image, - 'skills' => $skills, // مهارت‌ها اکنون بارگذاری شده‌اند + 'skills' => $skills, ]; return response()->json($data); diff --git a/app/Http/Controllers/Website/ProjectController.php b/app/Http/Controllers/Api/Website/ProjectController.php similarity index 91% rename from app/Http/Controllers/Website/ProjectController.php rename to app/Http/Controllers/Api/Website/ProjectController.php index eec335a..5b96981 100644 --- a/app/Http/Controllers/Website/ProjectController.php +++ b/app/Http/Controllers/Api/Website/ProjectController.php @@ -1,6 +1,6 @@ query('per_page', 10); // مقدار پیش‌فرض ۱۰ در نظر گرفته می‌شود + $perPage = request()->query('per_page', 10); - // Retrieve projects with translations and categories $projects = Project::with('translations', 'category.translations')->paginate($perPage); $formattedProjects = $projects->items(); @@ -53,12 +51,10 @@ public function index($locale): \Illuminate\Http\JsonResponse ]); } - public function store(StoreProjectRequest $request) { $project = Project::create($request->only(['category_id', 'image1', 'image2'])); - // ایجاد ترجمه‌ها foreach (['fa', 'en'] as $locale) { $project->translations()->create([ 'locale' => $locale, @@ -92,13 +88,11 @@ public function show($id) return response()->json(['project' => $formattedProject]); } - public function update(UpdateProjectRequest $request, $id) { $project = Project::findOrFail($id); $project->update($request->only(['category_id', 'image1', 'image2'])); - // به‌روزرسانی ترجمه‌ها foreach (['fa', 'en'] as $locale) { $project->translations()->updateOrCreate( ['locale' => $locale], diff --git a/app/Http/Controllers/Website/ServiceController.php b/app/Http/Controllers/Api/Website/ServiceController.php similarity index 77% rename from app/Http/Controllers/Website/ServiceController.php rename to app/Http/Controllers/Api/Website/ServiceController.php index edd38ab..53e9116 100644 --- a/app/Http/Controllers/Website/ServiceController.php +++ b/app/Http/Controllers/Api/Website/ServiceController.php @@ -1,23 +1,18 @@ function ($query) use ($locale) { $query->where('locale', $locale); }])->get(); - // فرمتی که می‌خواهیم به کاربر ارسال کنیم $response = $services->map(function ($service) use ($locale) { return [ 'id' => $service->id, @@ -33,9 +28,6 @@ public function index($locale) return response()->json($response); } - /** - * نمایش یک خدمت خاص با ترجمه - */ public function showTranslation($id, $locale) { $service = Service::with('translations')->findOrFail($id); diff --git a/app/Http/Controllers/Blog/CategoryController.php b/app/Http/Controllers/Blog/CategoryController.php deleted file mode 100644 index 324aa82..0000000 --- a/app/Http/Controllers/Blog/CategoryController.php +++ /dev/null @@ -1,144 +0,0 @@ -input('filter'); // فیلتر (به عنوان مثال، نام دسته‌بندی) - $sortBy = $request->input('sort_by', 'created_at'); // مرتب‌سازی (پیش‌فرض بر اساس زمان ایجاد) - $sortDirection = $request->input('sort_direction', 'desc'); // جهت مرتب‌سازی (پیش‌فرض نزولی) - $perPage = $request->input('per_page', 10); // تعداد آیتم‌ها در هر صفحه (پیش‌فرض ۱۰) - - // شروع کوئری با مدل دسته‌بندی و روابط - $query = Category::with('posts'); - - // اعمال فیلتر در صورت موجود بودن - if (!empty($filter)) { - $query->where('name', 'like', '%' . $filter . '%'); - } - - // اعمال مرتب‌سازی - $query->orderBy($sortBy, $sortDirection); - - // گرفتن نتایج با پجینیشن - $categories = $query->paginate($perPage); - - // بازگشت داده‌ها با استفاده از ریسورس - return CategoryResource::collection($categories); - } - - // نمایش یک دسته‌بندی خاص - public function show($id) - { - $category = Category::with('posts')->findOrFail($id); - return new CategoryResource($category); - } - - /** - * نمایش دسته‌بندی و پست‌های مرتبط با آن بر اساس slug - * - * @param \Illuminate\Http\Request $request - * @param string $slug - * @return \Illuminate\Http\JsonResponse - */ - public function getCategoryWithPosts(Request $request, $slug) -{ - // یافتن دسته‌بندی بر اساس slug - $category = Category::where('slug', $slug)->first(); - - if (!$category) { - return response()->json([ - 'message' => 'دسته‌بندی مورد نظر یافت نشد.' - ], 404); - } - - // دریافت تعداد پست‌ها در هر صفحه (پیش‌فرض: ۱۰) - $perPage = $request->input('per_page', 10); - - // دریافت فیلتر و سورت از درخواست - $filter = $request->input('filter'); // فیلتر (به عنوان مثال، عنوان پست) - $sortBy = $request->input('sort_by', 'published_at'); // مرتب‌سازی (پیش‌فرض بر اساس تاریخ انتشار) - $sortDirection = $request->input('sort_direction', 'desc'); // جهت مرتب‌سازی (پیش‌فرض نزولی) - - // شروع کوئری با پست‌های مربوط به دسته‌بندی - $postsQuery = $category->posts()->with(['category', 'tags', 'author']); - - // اعمال فیلتر در صورت موجود بودن - if (!empty($filter)) { - $postsQuery->where('title', 'like', '%' . $filter . '%'); - } - - // اعمال مرتب‌سازی - $postsQuery->orderBy($sortBy, $sortDirection); - - // گرفتن پست‌ها با پجینیشن - $posts = $postsQuery->paginate($perPage); - - // ساخت meta و links برای pagination - $meta = [ - 'total' => $posts->total(), - 'per_page' => $posts->perPage(), - 'current_page' => $posts->currentPage(), - 'last_page' => $posts->lastPage(), - 'from' => $posts->firstItem(), - 'to' => $posts->lastItem(), - ]; - - $links = [ - 'first' => $posts->url(1), - 'last' => $posts->url($posts->lastPage()), - 'prev' => $posts->previousPageUrl(), - 'next' => $posts->nextPageUrl(), - ]; - - // بازگشت اطلاعات دسته‌بندی و پست‌ها - return response()->json([ - 'category' => new CategoryResource($category), - 'posts' => PostResource::collection($posts), - 'meta' => $meta, - 'links' => $links, - ], 200); -} - - - - // ذخیره یک دسته‌بندی جدید - public function store(StoreCategoryRequest $request) - { - $category = Category::create($request->validated()); - - return new CategoryResource($category); - } - - // به‌روزرسانی یک دسته‌بندی خاص - public function update(UpdateCategoryRequest $request, $id) - { - $category = Category::findOrFail($id); - $category->update($request->validated()); - - return new CategoryResource($category); - } - - // حذف یک دسته‌بندی خاص - public function destroy($id) - { - $category = Category::findOrFail($id); - // قبل از حذف، مطمئن شوید که پست‌ها به دسته‌بندی دیگری منتقل شده‌اند یا حذف شوند - // برای سادگی، اینجا فقط دسته‌بندی را حذف می‌کنیم - $category->delete(); - - return response()->json(['message' => 'Category deleted successfully'], 200); - } -} diff --git a/app/Http/Resources/User.php b/app/Http/Resources/User.php deleted file mode 100644 index 97a875d..0000000 --- a/app/Http/Resources/User.php +++ /dev/null @@ -1,25 +0,0 @@ - - */ - public function toArray(Request $request): array - { - return [ - 'id' => $this->id, - 'name' => $this->name, - // اضافه کردن سایر فیلدهای مورد نیاز - 'email' => $this->email, - 'created_at' => $this->created_at, - ]; - } -} diff --git a/app/Http/Resources/UserCollection.php b/app/Http/Resources/UserCollection.php deleted file mode 100644 index cc7b28d..0000000 --- a/app/Http/Resources/UserCollection.php +++ /dev/null @@ -1,19 +0,0 @@ - - */ - public function toArray(Request $request): array - { - return parent::toArray($request); - } -} diff --git a/routes/api.php b/routes/api.php index 92247f1..18de6e0 100644 --- a/routes/api.php +++ b/routes/api.php @@ -1,18 +1,13 @@ user(); -})->middleware('auth:sanctum'); +use App\Http\Controllers\Api\Blog\CategoryController; +use App\Http\Controllers\Api\Blog\HomeController; +use App\Http\Controllers\Api\Blog\PostController; +use App\Http\Controllers\Api\Blog\TagController; +use App\Http\Controllers\Api\Website\AboutMeController; +use App\Http\Controllers\Api\Website\ProjectController; +use App\Http\Controllers\Api\Website\ServiceController; Route::middleware('throttle:60,1')->group(function () { Route::prefix('website')->group(function () {