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 () {