Compare commits

...

11 Commits

Author SHA1 Message Date
root
373402eb1b version e server e kharej 2025-04-16 10:06:15 +00:00
parsa aghaei
2c0a585bf8 service seeder updated 2024-11-11 12:02:13 +03:30
parsa aghaei
240bc7ccfb service seeder updated 2024-11-11 11:48:04 +03:30
parsa aghaei
ae33539f72 Merge branch 'develop' 2024-11-11 11:41:08 +03:30
parsa aghaei
6c834607bd multilanguage updated 2024-11-03 16:01:47 +03:30
b14a3189b4 merge with develop 2024-10-24 11:46:26 +03:30
parsa aghaei
027d1090df internationalization added and backend updated until services 2024-10-23 19:06:12 +03:30
parsa aghaei
9bcf1fb0eb sort and pagination added 2024-10-14 16:22:36 +03:30
parsa aghaei
d98bc7bbb0 blog api created 2024-10-13 20:16:08 +03:30
parsa aghaei
4f101885a8 initial 2024-09-25 14:32:49 +03:30
dbec761a0b
Initial commit 2024-09-25 13:04:04 +03:30
83 changed files with 2250 additions and 206 deletions

21
LICENSE Normal file
View File

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2024 parsa aghayi
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@ -0,0 +1,168 @@
<?php
namespace App\Http\Controllers\Blog;
use App\Http\Controllers\Controller;
use App\Http\Resources\CategoryResource;
use App\Http\Resources\PostResource;
use App\Models\Blog\Category;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Validator;
class CategoryController extends Controller
{
// نمایش لیست دسته‌بندی‌ها با صفحه‌بندی
public function index(Request $request)
{
// گرفتن فیلتر و سورت از درخواست کاربر
$filter = $request->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(Request $request)
{
$validator = Validator::make($request->all(), [
'name' => 'required|string|max:255|unique:categories,name',
'slug' => 'required|string|unique:categories,slug',
'description' => 'required|string',
'short_description' => 'nullable|string|max:500',
'image' => 'nullable|url',
]);
if ($validator->fails()) {
return response()->json($validator->errors(), 422);
}
$category = Category::create($validator->validated());
return new CategoryResource($category);
}
// به‌روزرسانی یک دسته‌بندی خاص
public function update(Request $request, $id)
{
$category = Category::findOrFail($id);
$validator = Validator::make($request->all(), [
'name' => 'sometimes|required|string|max:255|unique:categories,name,' . $category->id,
'slug' => 'sometimes|required|string|unique:categories,slug,' . $category->id,
'description' => 'sometimes|required|string',
'short_description' => 'nullable|string|max:500',
'image' => 'nullable|url',
]);
if ($validator->fails()) {
return response()->json($validator->errors(), 422);
}
$category->update($validator->validated());
return new CategoryResource($category);
}
// حذف یک دسته‌بندی خاص
public function destroy($id)
{
$category = Category::findOrFail($id);
// قبل از حذف، مطمئن شوید که پست‌ها به دسته‌بندی دیگری منتقل شده‌اند یا حذف شوند
// برای سادگی، اینجا فقط دسته‌بندی را حذف می‌کنیم
$category->delete();
return response()->json(['message' => 'Category deleted successfully'], 200);
}
}

View File

@ -0,0 +1,52 @@
<?php
namespace App\Http\Controllers\Blog;
use App\Http\Controllers\Controller;
use App\Http\Resources\CategoryResource;
use App\Http\Resources\PostResource;
use App\Models\Blog\Category;
use App\Models\Blog\Post;
use Illuminate\Http\Request;
class HomeController extends Controller
{
/**
* برگرداندن داده‌های مورد نیاز برای صفحه‌ی اصلی
*
* @return \Illuminate\Http\JsonResponse
*/
public function index()
{
// 1. 5 پست آخر
$latestPosts = Post::with(['category', 'tags', 'author'])
->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),
'most_viewed_posts' => PostResource::collection($mostViewedPosts),
'random_posts' => PostResource::collection($randomPosts),
], 200);
}
}

View File

@ -0,0 +1,127 @@
<?php
namespace App\Http\Controllers\Blog;
use App\Http\Controllers\Controller;
use App\Http\Resources\PostResource;
use App\Models\Blog\Post;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Validator;
class PostController extends Controller
{
// نمایش لیست پست‌ها با فیلتر و صفحه‌بندی
public function index(Request $request)
{
// دریافت پارامترهای فیلتر از درخواست
$filters = $request->only(['category', 'tag', 'search', 'author', 'published']);
// دریافت پارامترهای مرتب‌سازی از درخواست
$sortField = $request->get('sort_field', 'published_at'); // فیلد پیش‌فرض: published_at
$sortDirection = $request->get('sort_direction', 'desc'); // جهت پیش‌فرض: نزولی
// دریافت پارامترهای صفحه‌بندی از درخواست
$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 برمی‌گرداند
// بازگشت پست و پست‌های مرتبط به صورت JSON با استفاده از منابع
return response()->json([
'post' => new PostResource($post),
'related_posts' => PostResource::collection($post->relatedPosts->sortByDesc('published_at')->take(5)), // بازگشت ۵ پست مرتبط جدیدترین
], 200);
}
// ذخیره یک پست جدید
public function store(Request $request)
{
$validator = Validator::make($request->all(), [
'title' => 'required|string|max:255',
'body' => 'required|string',
'excerpt' => 'nullable|string|max:500',
'slug' => 'required|string|unique:posts,slug',
'author_id' => 'required|exists:users,id',
'category_id' => 'required|exists:categories,id',
'featured_image' => 'nullable|url',
'views' => 'nullable|integer',
'likes' => 'nullable|integer',
'published_at' => 'nullable|date',
'tags' => 'nullable|array',
'tags.*' => 'exists:tags,id',
]);
if ($validator->fails()) {
return response()->json($validator->errors(), 422);
}
$post = Post::create($validator->validated());
if ($request->has('tags')) {
$post->tags()->attach($request->tags);
}
return new PostResource($post->load(['category', 'tags', 'author']));
}
// به‌روزرسانی یک پست خاص
public function update(Request $request, $id)
{
$post = Post::findOrFail($id);
$validator = Validator::make($request->all(), [
'title' => 'sometimes|required|string|max:255',
'body' => 'sometimes|required|string',
'excerpt' => 'nullable|string|max:500',
'slug' => 'sometimes|required|string|unique:posts,slug,' . $post->id,
'author_id' => 'sometimes|required|exists:users,id',
'category_id' => 'sometimes|required|exists:categories,id',
'featured_image' => 'nullable|url',
'views' => 'nullable|integer',
'likes' => 'nullable|integer',
'published_at' => 'nullable|date',
'tags' => 'nullable|array',
'tags.*' => 'exists:tags,id',
]);
if ($validator->fails()) {
return response()->json($validator->errors(), 422);
}
$post->update($validator->validated());
if ($request->has('tags')) {
$post->tags()->sync($request->tags);
}
return new PostResource($post->load(['category', 'tags', 'author']));
}
// حذف یک پست خاص
public function destroy($id)
{
$post = Post::findOrFail($id);
$post->tags()->detach();
$post->relatedPosts()->detach();
$post->delete();
return response()->json(['message' => 'Post deleted successfully'], 200);
}
}

View File

@ -0,0 +1,72 @@
<?php
namespace App\Http\Controllers\Blog;
use App\Http\Controllers\Controller;
use App\Http\Resources\TagResource;
use App\Models\Blog\Tag;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Validator;
class TagController extends Controller
{
// نمایش لیست تگ‌ها با صفحه‌بندی
public function index(Request $request)
{
$tags = Tag::with('posts')->paginate(10);
return TagResource::collection($tags);
}
// نمایش یک تگ خاص
public function show($id)
{
$tag = Tag::with('posts')->findOrFail($id);
return new TagResource($tag);
}
// ذخیره یک تگ جدید
public function store(Request $request)
{
$validator = Validator::make($request->all(), [
'name' => 'required|string|max:255|unique:tags,name',
'slug' => 'required|string|unique:tags,slug',
]);
if ($validator->fails()) {
return response()->json($validator->errors(), 422);
}
$tag = Tag::create($validator->validated());
return new TagResource($tag);
}
// به‌روزرسانی یک تگ خاص
public function update(Request $request, $id)
{
$tag = Tag::findOrFail($id);
$validator = Validator::make($request->all(), [
'name' => 'sometimes|required|string|max:255|unique:tags,name,' . $tag->id,
'slug' => 'sometimes|required|string|unique:tags,slug,' . $tag->id,
]);
if ($validator->fails()) {
return response()->json($validator->errors(), 422);
}
$tag->update($validator->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);
}
}

View File

@ -0,0 +1,82 @@
<?php
namespace App\Http\Controllers\Website;
use Illuminate\Http\Request;
use App\Models\Website\AboutMe;
use App\Http\Controllers\Controller;
class AboutMeController extends Controller
{
public function index()
{
$aboutMe = AboutMe::with('skills.translations')->first(); // بارگذاری مهارت‌ها و ترجمه‌ها
return response()->json($aboutMe);
}
public function show($id)
{
$aboutMe = AboutMe::with('skills.translations')->findOrFail($id);
return response()->json($aboutMe);
}
public function store(Request $request)
{
$aboutMe = AboutMe::create($request->all());
return response()->json($aboutMe, 201);
}
public function update(Request $request, $id)
{
$aboutMe = AboutMe::findOrFail($id);
$aboutMe->update($request->all());
return response()->json($aboutMe);
}
public function destroy($id)
{
AboutMe::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(); // فقط یک ترجمه دریافت می‌کنیم
$skills = $aboutMe->skills->map(function ($skill) use ($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, // درصد
];
});
$data = [
'id' => $aboutMe->id,
'title' => $translation->title,
'description' => $translation->description,
'image' => $aboutMe->image,
'skills' => $skills, // مهارت‌ها اکنون بارگذاری شده‌اند
];
return response()->json($data);
}
}

View File

@ -0,0 +1,119 @@
<?php
namespace App\Http\Controllers\website;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use App\Models\Website\Project;
use App\Models\Website\ProjectCategory;
class ProjectController extends Controller
{
public function index($locale): \Illuminate\Http\JsonResponse
{
// Read per_page from query string or set a default value
$perPage = request()->query('per_page', 10); // مقدار پیش‌فرض ۱۰ در نظر گرفته می‌شود
// Retrieve projects with translations and categories
$projects = Project::with('translations', 'category.translations')->paginate($perPage);
$formattedProjects = $projects->items();
$formattedProjects = array_map(function ($project) use ($locale) {
$translation = $project->translations->firstWhere('locale', $locale);
$categoryTranslation = $project->category->translations->firstWhere('locale', $locale);
return [
'id' => $project->id,
'title' => $translation ? $translation->title : null,
'category' => $categoryTranslation ? $categoryTranslation->title : null,
'images' => [
['src' => $project->image1, 'position' => '1', 'zIndex' => 1],
['src' => $project->image2, 'position' => '2', 'zIndex' => 2],
],
'created_at' => $project->created_at,
'updated_at' => $project->updated_at,
];
}, $formattedProjects);
return response()->json([
'projects' => [
'current_page' => $projects->currentPage(),
'data' => $formattedProjects,
'total' => $projects->total(),
'last_page' => $projects->lastPage(),
],
'categories' => ProjectCategory::all()->map(function ($category) use ($locale) {
return [
'id' => $category->id,
'title' => $category->translations->firstWhere('locale', $locale)->title ?? null,
'image' => $category->image,
];
}),
]);
}
public function store(Request $request)
{
$project = Project::create($request->only(['category_id', 'image1', 'image2']));
// ایجاد ترجمه‌ها
foreach (['fa', 'en'] as $locale) {
$project->translations()->create([
'locale' => $locale,
'title' => $request->input("title_$locale"),
'description' => $request->input("description_$locale"),
]);
}
return response()->json($project->load('translations'), 201);
}
public function show($id)
{
$project = Project::with('translations', 'category.translations')->findOrFail($id);
$translation = $project->translations->firstWhere('locale', 'fa');
$categoryTranslation = $project->category->translations->firstWhere('locale', 'fa');
$formattedProject = [
'id' => $project->id,
'title' => $translation ? $translation->title : null,
'category' => $categoryTranslation ? $categoryTranslation->title : null,
'images' => [
['src' => $project->image1, 'position' => '1', 'zIndex' => 1],
['src' => $project->image2, 'position' => '2', 'zIndex' => 2],
],
'created_at' => $project->created_at,
'updated_at' => $project->updated_at,
];
return response()->json(['project' => $formattedProject]);
}
public function update(Request $request, $id)
{
$project = Project::findOrFail($id);
$project->update($request->only(['category_id', 'image1', 'image2']));
// به‌روزرسانی ترجمه‌ها
foreach (['fa', 'en'] as $locale) {
$project->translations()->updateOrCreate(
['locale' => $locale],
[
'title' => $request->input("title_$locale"),
'description' => $request->input("description_$locale"),
]
);
}
return response()->json($project->load('translations'));
}
public function destroy($id)
{
Project::destroy($id);
return response()->json(null, 204);
}
}

View File

@ -0,0 +1,50 @@
<?php
namespace App\Http\Controllers\Website;
use App\Http\Controllers\Controller;
use App\Models\Website\Service;
class ServiceController extends Controller
{
/**
* دریافت لیست خدمات با ترجمه‌ها بر اساس زبان
*/
public function index($locale)
{
// گرفتن همه خدمات به همراه ترجمه‌ها
$services = Service::with(['translations' => function ($query) use ($locale) {
$query->where('locale', $locale);
}])->get();
// فرمتی که می‌خواهیم به کاربر ارسال کنیم
$response = $services->map(function ($service) use ($locale) {
return [
'id' => $service->id,
'imageSrc' => $service->imageSrc,
'altText' => $service->translations->first()->altText ?? '',
'created_at' => $service->created_at,
'updated_at' => $service->updated_at,
'title' => optional($service->translations->first())->title,
'description' => optional($service->translations->first())->description,
];
});
return response()->json($response);
}
/**
* نمایش یک خدمت خاص با ترجمه
*/
public function showTranslation($id, $locale)
{
$service = Service::with('translations')->findOrFail($id);
return response()->json([
'id' => $service->id,
'imageSrc' => $service->imageSrc,
'title' => $service->getTitle($locale),
'description' => $service->getDescription($locale),
]);
}
}

View File

@ -0,0 +1,32 @@
<?php
namespace App\Http\Resources;
use Carbon\Carbon;
use Illuminate\Http\Request;
use Illuminate\Http\Resources\Json\JsonResource;
class CategoryResource extends JsonResource
{
/**
* Transform the resource into an array.
*
* @return array<string, mixed>
*/
public function toArray(Request $request): array
{
return [
'id' => $this->id,
'name' => $this->name,
'slug' => $this->slug,
'description' => $this->description,
'short_description' => $this->short_description,
'image' => $this->image,
'posts_count' => $this->whenLoaded('posts', function () {
return $this->posts->count();
}),
'created_at' => Carbon::parse($this->created_at)->format('M d Y'),
'updated_at' => Carbon::parse($this->updated_at)->format('M d Y'),
];
}
}

View File

@ -0,0 +1,35 @@
<?php
namespace App\Http\Resources;
use Illuminate\Http\Request;
use Illuminate\Http\Resources\Json\JsonResource;
use Carbon\Carbon;
class PostResource extends JsonResource
{
/**
* Transform the resource into an array.
*
* @return array<string, mixed>
*/
public function toArray(Request $request): array
{
return [
'id' => $this->id,
'title' => $this->title,
'slug' => $this->slug,
'excerpt' => $this->excerpt,
'body' => $this->body,
'author' => new UserResource($this->author),
'category' => new CategoryResource($this->category),
'tags' => TagResource::collection($this->tags),
'featured_image' => $this->featured_image,
'views' => $this->views,
'likes' => $this->likes,
'published_at' => $this->published_at,
'created_at' => Carbon::parse($this->created_at)->format('M d Y'),
'updated_at' => Carbon::parse($this->updated_at)->format('M d Y'),
];
}
}

View File

@ -0,0 +1,29 @@
<?php
namespace App\Http\Resources;
use Carbon\Carbon;
use Illuminate\Http\Request;
use Illuminate\Http\Resources\Json\JsonResource;
class TagResource extends JsonResource
{
/**
* Transform the resource into an array.
*
* @return array<string, mixed>
*/
public function toArray(Request $request): array
{
return [
'id' => $this->id,
'name' => $this->name,
'slug' => $this->slug,
'posts_count' => $this->whenLoaded('posts', function () {
return $this->posts->count();
}),
'created_at' => Carbon::parse($this->created_at)->format('M d Y'),
'updated_at' => Carbon::parse($this->updated_at)->format('M d Y'),
];
}
}

View File

@ -14,6 +14,12 @@ class User extends ResourceCollection
*/
public function toArray(Request $request): array
{
return parent::toArray($request);
return [
'id' => $this->id,
'name' => $this->name,
// اضافه کردن سایر فیلدهای مورد نیاز
'email' => $this->email,
'created_at' => $this->created_at,
];
}
}

View File

@ -1,7 +1,8 @@
<?php
namespace App\Http\Resources;
use Carbon\Carbon;
use Illuminate\Http\Request;
use Illuminate\Http\Resources\Json\JsonResource;
@ -18,8 +19,8 @@ public function toArray(Request $request): array
'id' => $this->id,
'name' => $this->name,
'email' => $this->email,
'created_at' => $this->created_at,
'updated_at' => $this->updated_at,
'created_at' => Carbon::parse($this->created_at)->format('M d Y'),
'updated_at' => Carbon::parse($this->updated_at)->format('M d Y'),
];
}
}

View File

@ -0,0 +1,25 @@
<?php
namespace App\Models\Blog;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Category extends Model
{
use HasFactory;
protected $fillable = [
'name',
'slug',
'description',
'short_description',
'image',
];
// رابطه با پست‌ها
public function posts()
{
return $this->hasMany(Post::class);
}
}

99
app/Models/Blog/Post.php Normal file
View File

@ -0,0 +1,99 @@
<?php
namespace App\Models\Blog;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use App\Models\User;
class Post extends Model
{
use HasFactory;
protected $fillable = [
'title',
'body',
'excerpt',
'slug',
'author_id',
'category_id',
'featured_image',
'views',
'likes',
'published_at',
];
// رابطه با نویسنده
public function author()
{
return $this->belongsTo(User::class, 'author_id');
}
// رابطه با دسته‌بندی
public function category()
{
return $this->belongsTo(Category::class);
}
// رابطه با تگ‌ها
public function tags()
{
return $this->belongsToMany(Tag::class)->withTimestamps();
}
// پست‌های مرتبط
public function relatedPosts()
{
return $this->belongsToMany(Post::class, 'related_posts', 'post_id', 'related_post_id')->withTimestamps();
}
// اسکوپ فیلتر
public function scopeFilter($query, $filters)
{
if (isset($filters['category'])) {
$query->whereHas('category', function ($q) use ($filters) {
$q->where('slug', $filters['category']);
});
}
if (isset($filters['tag'])) {
$query->whereHas('tags', function ($q) use ($filters) {
$q->where('slug', $filters['tag']);
});
}
if (isset($filters['search'])) {
$query->where(function ($q) use ($filters) {
$q->where('title', 'like', '%' . $filters['search'] . '%')
->orWhere('body', 'like', '%' . $filters['search'] . '%');
});
}
if (isset($filters['author'])) {
$query->whereHas('author', function ($q) use ($filters) {
$q->where('id', $filters['author']);
});
}
if (isset($filters['published'])) {
$query->whereNotNull('published_at');
}
return $query;
}
/**
* Scope برای اعمال مرتب‌سازی
*/
public function scopeSort($query, $sortField, $sortDirection = 'asc')
{
// بررسی اینکه فیلد مرتب‌سازی معتبر است یا خیر
$allowedSortFields = ['published_at', 'views', 'likes', 'title'];
if (in_array($sortField, $allowedSortFields)) {
$sortDirection = strtolower($sortDirection) === 'desc' ? 'desc' : 'asc';
$query->orderBy($sortField, $sortDirection);
}
return $query;
}
}

22
app/Models/Blog/Tag.php Normal file
View File

@ -0,0 +1,22 @@
<?php
namespace App\Models\Blog;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Tag extends Model
{
use HasFactory;
protected $fillable = [
'name',
'slug',
];
// رابطه با پست‌ها
public function posts()
{
return $this->belongsToMany(Post::class)->withTimestamps();
}
}

View File

@ -3,6 +3,8 @@
namespace App\Models;
// use Illuminate\Contracts\Auth\MustVerifyEmail;
use App\Models\Blog\Post;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
@ -44,4 +46,9 @@ protected function casts(): array
'password' => 'hashed',
];
}
public function posts()
{
return $this->hasMany(Post::class, 'author_id');
}
}

View File

@ -0,0 +1,53 @@
<?php
namespace App\Models\Website;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class AboutMe extends Model
{
use HasFactory;
protected $table = 'website_about_me';
protected $fillable = ['image'];
/**
* ارتباط با ترجمه‌ها
*/
public function translations()
{
return $this->hasMany(AboutMeTranslation::class, 'about_me_id');
}
/**
* گرفتن ترجمه بر اساس زبان فعلی
*/
public function getTranslation($locale)
{
return $this->translations()->where('locale', $locale)->first();
}
/**
* گرفتن عنوان بر اساس زبان فعلی
*/
public function getTitle($locale)
{
$translation = $this->getTranslation($locale);
return $translation ? $translation->title : null;
}
/**
* گرفتن توضیحات بر اساس زبان فعلی
*/
public function getDescription($locale)
{
$translation = $this->getTranslation($locale);
return $translation ? $translation->description : null;
}
public function skills()
{
return $this->hasMany(Skill::class);
}
}

View File

@ -0,0 +1,22 @@
<?php
namespace App\Models\Website;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class AboutMeTranslation extends Model
{
use HasFactory;
protected $table = 'website_about_me_translations';
protected $fillable = ['about_me_id', 'locale', 'title', 'description'];
/**
* ارتباط با AboutMe
*/
public function aboutMe()
{
return $this->belongsTo(AboutMe::class, 'about_me_id');
}
}

View File

@ -0,0 +1,24 @@
<?php
namespace App\Models\Website;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Project extends Model
{
use HasFactory;
protected $table = 'website_projects'; // نام صحیح جدول
protected $fillable = ['category_id', 'image1', 'image2'];
public function translations()
{
return $this->hasMany(ProjectTranslation::class, 'project_id');
}
public function category()
{
return $this->belongsTo(ProjectCategory::class, 'category_id');
}
}

View File

@ -0,0 +1,19 @@
<?php
namespace App\Models\Website;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class ProjectCategory extends Model
{
use HasFactory;
protected $table = 'website_project_categories'; // نام صحیح جدول
protected $fillable = ['image'];
public function translations()
{
return $this->hasMany(ProjectCategoryTranslation::class, 'category_id');
}
}

View File

@ -0,0 +1,14 @@
<?php
namespace App\Models\Website;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class ProjectCategoryTranslation extends Model
{
use HasFactory;
protected $table = 'website_project_category_translations'; // نام صحیح جدول
protected $fillable = ['category_id', 'locale', 'title', 'description'];
}

View File

@ -0,0 +1,19 @@
<?php
namespace App\Models\Website;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class ProjectTranslation extends Model
{
use HasFactory;
protected $table = 'website_project_translations'; // نام صحیح جدول
protected $fillable = ['project_id', 'locale', 'title', 'description'];
public function project()
{
return $this->belongsTo(Project::class, 'project_id');
}
}

View File

@ -0,0 +1,48 @@
<?php
namespace App\Models\Website;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Service extends Model
{
use HasFactory;
protected $table = 'website_services'; // نام جدول
protected $fillable = ['imageSrc']; // فیلدهایی که قابل پر کردن هستند
/**
* ارتباط با جدول ترجمه‌ها
*/
public function translations()
{
return $this->hasMany(ServiceTranslation::class, 'service_id');
}
/**
* گرفتن ترجمه بر اساس زبان فعلی
*/
public function getTranslation($locale)
{
return $this->translations()->where('locale', $locale)->first();
}
/**
* گرفتن عنوان بر اساس زبان فعلی
*/
public function getTitle($locale)
{
$translation = $this->getTranslation($locale);
return $translation ? $translation->title : null;
}
/**
* گرفتن توضیحات بر اساس زبان فعلی
*/
public function getDescription($locale)
{
$translation = $this->getTranslation($locale);
return $translation ? $translation->description : null;
}
}

View File

@ -0,0 +1,22 @@
<?php
namespace App\Models\Website;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class ServiceTranslation extends Model
{
use HasFactory;
protected $table = 'website_service_translations'; // نام جدول
protected $fillable = ['service_id', 'locale', 'title', 'description']; // فیلدهایی که قابل پر کردن هستند
/**
* ارتباط با جدول خدمات
*/
public function service()
{
return $this->belongsTo(Service::class, 'service_id');
}
}

View File

@ -0,0 +1,56 @@
<?php
namespace App\Models\Website;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Skill extends Model
{
use HasFactory;
protected $table = 'website_skills'; // نام جدول
protected $fillable = ['image', 'link', 'about_me_id', 'percentage']; // فیلدهایی که قابل پر کردن هستند
/**
* ارتباط با جدول AboutMe
*/
public function aboutMe()
{
return $this->belongsTo(AboutMe::class, 'about_me_id');
}
/**
* ارتباط با جدول ترجمه‌ها
*/
public function translations()
{
return $this->hasMany(SkillTranslation::class, 'skill_id');
}
/**
* گرفتن ترجمه بر اساس زبان فعلی
*/
public function getTranslation($locale)
{
return $this->translations()->where('locale', $locale)->first();
}
/**
* گرفتن عنوان بر اساس زبان فعلی
*/
public function getTitle($locale)
{
$translation = $this->getTranslation($locale);
return $translation ? $translation->title : null;
}
/**
* گرفتن توضیحات بر اساس زبان فعلی
*/
public function getDescription($locale)
{
$translation = $this->getTranslation($locale);
return $translation ? $translation->description : null;
}
}

View File

@ -0,0 +1,22 @@
<?php
namespace App\Models\Website;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class SkillTranslation extends Model
{
use HasFactory;
protected $table = 'website_skill_translations'; // نام جدول
protected $fillable = ['skill_id', 'locale', 'title', 'description']; // فیلدهایی که قابل پر کردن هستند
/**
* ارتباط با جدول Skills
*/
public function skill()
{
return $this->belongsTo(Skill::class, 'skill_id');
}
}

Binary file not shown.

0
bootstrap/cache/.gitignore vendored Normal file → Executable file
View File

34
config/cors.php Normal file
View File

@ -0,0 +1,34 @@
<?php
return [
/*
|--------------------------------------------------------------------------
| Cross-Origin Resource Sharing (CORS) Configuration
|--------------------------------------------------------------------------
|
| Here you may configure your settings for cross-origin resource sharing
| or "CORS". This determines what cross-origin operations may execute
| in web browsers. You are free to adjust these settings as needed.
|
| To learn more: https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS
|
*/
'paths' => ['api/*', 'sanctum/csrf-cookie'],
'allowed_methods' => ['*'],
'allowed_origins' => ['*'],
'allowed_origins_patterns' => [],
'allowed_headers' => ['*'],
'exposed_headers' => [],
'max_age' => 0,
'supports_credentials' => true,
];

View File

@ -0,0 +1,29 @@
<?php
namespace Database\Factories\Blog;
use Illuminate\Database\Eloquent\Factories\Factory;
use Illuminate\Support\Str;
/**
* @extends \Illuminate\Database\Eloquent\Factories\Factory<\App\Models\Category>
*/
class CategoryFactory extends Factory
{
/**
* Define the model's default state.
*
* @return array<string, mixed>
*/
public function definition(): array
{
$name = $this->faker->unique()->word;
return [
'name' => ucfirst($name),
'slug' => Str::slug($name),
'description' => $this->faker->paragraph,
'short_description' => $this->faker->sentence,
'image' => $this->faker->imageUrl(640, 480, 'business', true),
];
}
}

View File

@ -0,0 +1,41 @@
<?php
namespace Database\Factories\Blog;
use Illuminate\Database\Eloquent\Factories\Factory;
use App\Models\Blog\Post;
use App\Models\Blog\Category;
use App\Models\User;
use Illuminate\Support\Str;
/**
* @extends \Illuminate\Database\Eloquent\Factories\Factory<\App\Models\Tag>
*/
class PostFactory extends Factory
{
/**
* Define the model's default state.
*
* @return array<string, mixed>
*/
protected $model = Post::class;
public function definition(): array
{
$title = $this->faker->sentence;
return [
'title' => $title,
'body' => $this->faker->paragraphs(5, true),
'excerpt' => $this->faker->text(200),
'slug' => Str::slug($title) . '-' . $this->faker->unique()->numberBetween(1, 1000),
'author_id' => User::inRandomOrder()->first()->id ?? User::factory(),
'category_id' => Category::inRandomOrder()->first()->id ?? Category::factory(),
'featured_image' => $this->faker->imageUrl(800, 600, 'technics', true),
'views' => $this->faker->numberBetween(0, 1000),
'likes' => $this->faker->numberBetween(0, 500),
'published_at' => $this->faker->dateTimeBetween('-1 years', 'now'),
];
}
}

View File

@ -0,0 +1,30 @@
<?php
namespace Database\Factories\Blog;
use App\Models\Blog\Tag;
use Illuminate\Database\Eloquent\Factories\Factory;
use Illuminate\Support\Str;
/**
* @extends \Illuminate\Database\Eloquent\Factories\Factory<\App\Models\Tag>
*/
class TagFactory extends Factory
{
/**
* Define the model's default state.
*
* @return array<string, mixed>
*/
protected $model = Tag::class;
public function definition(): array
{
$name = $this->faker->unique()->word;
return [
'name' => ucfirst($name),
'slug' => Str::slug($name),
];
}
}

View File

@ -37,7 +37,7 @@ public function definition(): array
*/
public function unverified(): static
{
return $this->state(fn (array $attributes) => [
return $this->state(fn(array $attributes) => [
'email_verified_at' => null,
]);
}

View File

@ -1,32 +0,0 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('skills', function (Blueprint $table) {
$table->id();
$table->string('title');
$table->string('image'); // URL تصویر
$table->text('description'); // توضیحات
$table->string('link'); // لینک
$table->foreignId('about_me_id')->constrained('about_me')->onDelete('cascade'); // ارتباط با جدول about_me
$table->timestamps();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('skills');
}
};

View File

@ -1,28 +0,0 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up()
{
Schema::table('skills', function (Blueprint $table) {
$table->integer('percentage')->after('description'); // اضافه کردن ستون درصد
});
}
/**
* Reverse the migrations.
*/
public function down()
{
Schema::table('skills', function (Blueprint $table) {
$table->dropColumn('percentage');
});
}
};

View File

@ -0,0 +1,32 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('categories', function (Blueprint $table) {
$table->id();
$table->string('name')->unique();
$table->string('slug')->unique();
$table->text('description');
$table->text('short_description')->nullable();
$table->string('image')->nullable();
$table->timestamps();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('categories');
}
};

View File

@ -11,11 +11,10 @@
*/
public function up(): void
{
Schema::create('about_me', function (Blueprint $table) {
Schema::create('tags', function (Blueprint $table) {
$table->id();
$table->string('title');
$table->text('description');
$table->string('image'); // URL تصویر
$table->string('name')->unique();
$table->string('slug')->unique();
$table->timestamps();
});
}
@ -25,6 +24,6 @@ public function up(): void
*/
public function down(): void
{
Schema::dropIfExists('about_me');
Schema::dropIfExists('tags');
}
};

View File

@ -0,0 +1,39 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('posts', function (Blueprint $table) {
$table->id();
$table->string('title');
$table->text('body');
$table->text('excerpt'); // توضیحات مختصر
$table->string('slug')->unique();
$table->unsignedBigInteger('author_id'); // نویسنده
$table->foreign('author_id')->references('id')->on('users')->onDelete('cascade');
$table->unsignedBigInteger('category_id'); // دسته بندی
$table->foreign('category_id')->references('id')->on('categories')->onDelete('cascade');
$table->string('featured_image')->nullable(); // تصویر شاخص
$table->integer('views')->default(0); // تعداد بازدید
$table->integer('likes')->default(0); // تعداد لایک
$table->timestamp('published_at')->nullable(); // تاریخ انتشار
$table->timestamps();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('posts');
}
};

View File

@ -0,0 +1,36 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('post_tag', function (Blueprint $table) {
$table->id();
$table->unsignedBigInteger('post_id');
$table->unsignedBigInteger('tag_id');
$table->timestamps();
// ایجاد کلیدهای خارجی
$table->foreign('post_id')->references('id')->on('posts')->onDelete('cascade');
$table->foreign('tag_id')->references('id')->on('tags')->onDelete('cascade');
// جلوگیری از ورود تکراری
$table->unique(['post_id', 'tag_id']);
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('post_tag');
}
};

View File

@ -0,0 +1,36 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('related_posts', function (Blueprint $table) {
$table->id();
$table->unsignedBigInteger('post_id');
$table->unsignedBigInteger('related_post_id');
$table->timestamps();
// ایجاد کلیدهای خارجی
$table->foreign('post_id')->references('id')->on('posts')->onDelete('cascade');
$table->foreign('related_post_id')->references('id')->on('posts')->onDelete('cascade');
// جلوگیری از ورود تکراری
$table->unique(['post_id', 'related_post_id']);
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('related_posts');
}
};

View File

@ -0,0 +1,48 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
// جدول اصلی about_me
Schema::create('website_about_me', function (Blueprint $table) {
$table->id();
$table->string('image'); // URL تصویر
$table->timestamps();
});
// جدول ترجمه برای about_me
Schema::create('website_about_me_translations', function (Blueprint $table) {
$table->id();
$table->unsignedBigInteger('about_me_id');
$table->string('locale')->index(); // زبان (fa, en و غیره)
$table->string('title');
$table->text('description');
$table->timestamps();
// ارتباط با جدول اصلی
$table->foreign('about_me_id')->references('id')->on('website_about_me')->onDelete('cascade');
// جلوگیری از تکرار یک زبان برای هر about_me
$table->unique(['about_me_id', 'locale']);
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
// ابتدا جدول ترجمه باید حذف شود
Schema::dropIfExists('website_about_me_translations');
// سپس جدول اصلی حذف می‌شود
Schema::dropIfExists('website_about_me');
}
};

View File

@ -0,0 +1,46 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
// جدول اصلی skills
Schema::create('website_skills', function (Blueprint $table) {
$table->id();
$table->string('image'); // URL تصویر
$table->string('link')->nullable(); // لینک
$table->foreignId('about_me_id')->constrained('website_about_me')->onDelete('cascade'); // ارتباط با جدول website_about_me
$table->integer('percentage'); // درصد
$table->timestamps();
});
// جدول ترجمه برای skills
Schema::create('website_skill_translations', function (Blueprint $table) {
$table->id();
$table->foreignId('skill_id')->constrained('website_skills')->onDelete('cascade'); // ارتباط با جدول website_skills
$table->string('locale')->index(); // مشخص کردن زبان
$table->string('title'); // عنوان ترجمه‌شده
$table->text('description'); // توضیحات ترجمه‌شده
$table->unique(['skill_id', 'locale']); // جلوگیری از تکرار ترجمه برای هر زبان
$table->timestamps();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
// ابتدا جدول ترجمه باید حذف شود
Schema::dropIfExists('website_skill_translations');
// سپس جدول اصلی حذف می‌شود
Schema::dropIfExists('website_skills');
}
};

View File

@ -0,0 +1,48 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
// جدول اصلی services
Schema::create('website_services', function (Blueprint $table) {
$table->id();
$table->string('imageSrc'); // URL تصویر
$table->timestamps();
});
// جدول ترجمه برای services
Schema::create('website_service_translations', function (Blueprint $table) {
$table->id();
$table->unsignedBigInteger('service_id'); // کلید خارجی به جدول اصلی
$table->string('locale')->index(); // زبان (fa, en و غیره)
$table->string('title'); // عنوان ترجمه‌شده
$table->text('description'); // توضیحات ترجمه‌شده
$table->timestamps();
// ارتباط با جدول اصلی
$table->foreign('service_id')->references('id')->on('website_services')->onDelete('cascade');
// جلوگیری از تکرار یک زبان برای هر سرویس
$table->unique(['service_id', 'locale']);
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
// ابتدا جدول ترجمه باید حذف شود
Schema::dropIfExists('website_service_translations');
// سپس جدول اصلی حذف می‌شود
Schema::dropIfExists('website_services');
}
};

View File

@ -0,0 +1,50 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
// جدول اصلی testimonials
Schema::create('website_testimonials', function (Blueprint $table) {
$table->id();
$table->string('image'); // URL تصویر
$table->string('client_link'); // لینک از طرف
$table->timestamps();
});
// جدول ترجمه برای testimonials
Schema::create('website_testimonial_translations', function (Blueprint $table) {
$table->id();
$table->unsignedBigInteger('testimonial_id'); // کلید خارجی به جدول اصلی
$table->string('locale')->index(); // زبان (fa, en و غیره)
$table->string('client_name'); // نام ترجمه‌شده
$table->string('client_position'); // سمت ترجمه‌شده
$table->text('feedback'); // نظر ترجمه‌شده
$table->timestamps();
// ارتباط با جدول اصلی
$table->foreign('testimonial_id')->references('id')->on('website_testimonials')->onDelete('cascade');
// جلوگیری از تکرار یک زبان برای هر testimonial
$table->unique(['testimonial_id', 'locale']);
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
// ابتدا جدول ترجمه باید حذف شود
Schema::dropIfExists('website_testimonial_translations');
// سپس جدول اصلی حذف می‌شود
Schema::dropIfExists('website_testimonials');
}
};

View File

@ -0,0 +1,48 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
// جدول اصلی website_project_categories
Schema::create('website_project_categories', function (Blueprint $table) {
$table->id();
$table->string('image'); // URL تصویر
$table->timestamps();
});
// جدول ترجمه برای website_project_categories
Schema::create('website_project_category_translations', function (Blueprint $table) {
$table->id();
$table->unsignedBigInteger('category_id'); // کلید خارجی به جدول اصلی
$table->string('locale')->index(); // زبان (fa, en و غیره)
$table->string('title'); // عنوان ترجمه‌شده
$table->text('description'); // توضیحات ترجمه‌شده
$table->timestamps();
// ارتباط با جدول اصلی
$table->foreign('category_id')->references('id')->on('website_project_categories')->onDelete('cascade');
// جلوگیری از تکرار یک زبان برای هر دسته‌بندی
$table->unique(['category_id', 'locale']);
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
// ابتدا جدول ترجمه باید حذف شود
Schema::dropIfExists('website_project_category_translations');
// سپس جدول اصلی حذف می‌شود
Schema::dropIfExists('website_project_categories');
}
};

View File

@ -0,0 +1,50 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
// جدول اصلی website_projects
Schema::create('website_projects', function (Blueprint $table) {
$table->id();
$table->foreignId('category_id')->constrained('website_project_categories')->onDelete('cascade'); // کلید خارجی به جدول categories
$table->string('image1');
$table->string('image2');
$table->timestamps();
});
// جدول ترجمه برای website_projects
Schema::create('website_project_translations', function (Blueprint $table) {
$table->id();
$table->unsignedBigInteger('project_id'); // کلید خارجی به جدول اصلی
$table->string('locale')->index(); // زبان (fa, en و غیره)
$table->string('title'); // عنوان ترجمه‌شده
$table->text('description'); // توضیحات ترجمه‌شده
$table->timestamps();
// ارتباط با جدول اصلی
$table->foreign('project_id')->references('id')->on('website_projects')->onDelete('cascade');
// جلوگیری از تکرار یک زبان برای هر پروژه
$table->unique(['project_id', 'locale']);
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
// ابتدا جدول ترجمه باید حذف شود
Schema::dropIfExists('website_project_translations');
// سپس جدول اصلی حذف می‌شود
Schema::dropIfExists('website_projects');
}
};

View File

@ -1,59 +0,0 @@
<?php
namespace Database\Seeders;
use App\Models\AboutMe;
use App\Models\Skill;
use Illuminate\Database\Console\Seeds\WithoutModelEvents;
use Illuminate\Database\Seeder;
class AboutMeSeeder extends Seeder
{
/**
* Run the database seeds.
*/
public function run()
{
// ایجاد رکورد AboutMe
$aboutMe = AboutMe::create([
'title' => 'About Me Title',
'description' => 'This is a brief description about me.',
'image' => '/images/profile.png',
]);
// ایجاد رکوردهای Skill
Skill::create([
'title' => 'FrontEnd',
'image' => '/images/frontend.png',
'description' => 'UI design description.',
'link' => 'http://example.com/frontend',
'percentage' => 90,
'about_me_id' => $aboutMe->id,
]);
Skill::create([
'title' => 'BackEnd',
'image' => '/images/backend.png',
'description' => 'BackEnd description.',
'link' => 'http://example.com/backend',
'percentage' => 80,
'about_me_id' => $aboutMe->id,
]);
Skill::create([
'title' => 'UI Design',
'image' => '/images/ui.png',
'description' => 'UI design description.',
'link' => 'http://example.com/ui',
'percentage' => 70,
'about_me_id' => $aboutMe->id,
]);
Skill::create([
'title' => 'UX Design',
'image' => '/images/ux.png',
'description' => 'UX design description.',
'link' => 'http://example.com/ux',
'percentage' => 83,
'about_me_id' => $aboutMe->id,
]);
}
}

View File

@ -0,0 +1,46 @@
<?php
namespace Database\Seeders\Blog;
use App\Models\Blog\Category;
use App\Models\Blog\Post;
use App\Models\Blog\Tag;
use App\Models\User;
use Illuminate\Database\Seeder;
class BlogSeeder extends Seeder
{
/**
* Run the database seeds.
*/
public function run(): void
{
// انتخاب کاربر با id = 1
$user = User::find(1);
if (!$user) {
// اگر کاربر با id 1 وجود نداشت، خطا ایجاد کن یا پیام مناسبی بده
$this->command->error('User with id 1 not found.');
return;
}
// ایجاد دسته‌بندی‌ها
Category::factory(10)->create();
// ایجاد تگ‌ها
Tag::factory(20)->create();
// ایجاد پست‌ها و تخصیص به کاربر با id = 1
Post::factory(50)->create([
'author_id' => $user->id, // اختصاص پست‌ها به کاربر id 1
])->each(function ($post) {
// اختصاص تگ‌ها به پست
$tags = Tag::inRandomOrder()->take(rand(2, 5))->pluck('id');
$post->tags()->attach($tags);
// ایجاد پست‌های مرتبط
$relatedPosts = Post::inRandomOrder()->where('id', '!=', $post->id)->take(rand(1, 3))->pluck('id');
$post->relatedPosts()->attach($relatedPosts);
});
}
}

View File

@ -3,7 +3,11 @@
namespace Database\Seeders;
use App\Models\User;
// use Illuminate\Database\Console\Seeds\WithoutModelEvents;
use Database\Seeders\Blog\BlogSeeder;
use Database\Seeders\Website\AboutMeSeeder;
use Database\Seeders\Website\ProjectCategorySeeder;
use Database\Seeders\Website\ProjectSeeder;
use Database\Seeders\Website\ServiceSeeder;
use Illuminate\Database\Seeder;
class DatabaseSeeder extends Seeder
@ -16,11 +20,16 @@ public function run(): void
// User::factory(10)->create();
User::factory()->create([
'name' => 'Test User',
'email' => 'test@example.com',
'name' => 'parsa aghayi',
'email' => 'ceo@parsaaghayi.ir',
]);
$this->call([
AboutMeSeeder::class,
// ProjectSeeder::class,
ProjectCategorySeeder::class,
ProjectSeeder::class,
ServiceSeeder::class,
BlogSeeder::class
// دیگر seeders
]);
}

View File

@ -1,18 +0,0 @@
<?php
namespace Database\Seeders;
use Illuminate\Database\Console\Seeds\WithoutModelEvents;
use Illuminate\Database\Seeder;
use App\Models\Project;
class ProjectSeeder extends Seeder
{
/**
* Run the database seeds.
*/
public function run()
{
Project::factory()->count(100)->create();
}
}

View File

@ -1,47 +0,0 @@
<?php
namespace Database\Seeders;
use Illuminate\Database\Console\Seeds\WithoutModelEvents;
use Illuminate\Database\Seeder;
use App\Models\Service;
class ServiceSeeder extends Seeder
{
/**
* Run the database seeds.
*/
public function run()
{
$services = [
[
'title' => 'UI/UX',
'description' => 'Lorem ipsum dolor sit amet consectetur. Morbi diam nisi nam diam interdum',
'imageSrc' => '/images/ui-ux-vector.svg',
'altText' => 'UI/UX Vector',
],
[
'title' => 'Web Design',
'description' => 'Lorem ipsum dolor sit amet consectetur. Morbi diam nisi nam diam interdum',
'imageSrc' => '/images/web-design-vector.svg',
'altText' => 'Web Design Vector',
],
[
'title' => 'App Design',
'description' => 'Lorem ipsum dolor sit amet consectetur. Morbi diam nisi nam diam interdum',
'imageSrc' => '/images/app-design-vector.svg',
'altText' => 'App Design Vector',
],
[
'title' => 'Graphic Design',
'description' => 'Lorem ipsum dolor sit amet consectetur. Morbi diam nisi nam diam interdum',
'imageSrc' => '/images/graphic-design-vector.svg',
'altText' => 'Graphic Design Vector',
],
];
foreach ($services as $service) {
Service::create($service);
}
}
}

View File

@ -0,0 +1,151 @@
<?php
namespace Database\Seeders\Website;
use App\Models\Website\AboutMe;
use App\Models\Website\AboutMeTranslation;
use App\Models\Website\Skill;
use App\Models\Website\SkillTranslation;
use Illuminate\Database\Seeder;
class AboutMeSeeder extends Seeder
{
/**
* Run the database seeds.
*/
public function run()
{
// ایجاد رکورد AboutMe بدون ترجمه
$aboutMe = AboutMe::create([
'image' => '/images/profile.png',
]);
// ایجاد ترجمه انگلیسی
AboutMeTranslation::create([
'about_me_id' => $aboutMe->id,
'locale' => 'en',
'title' => 'About Me',
'description' => 'I am a web developer with over 10 years of experience in creating dynamic and user-centric web applications. Specializing in React and Next.js, I build scalable solutions that enhance performance and user experience. I enjoy tackling complex challenges, from improving legacy systems to developing new applications. My focus on frontend development and seamless backend integration allows me to deliver innovative results while staying current with industry trends.',
]);
// ایجاد ترجمه فارسی
AboutMeTranslation::create([
'about_me_id' => $aboutMe->id,
'locale' => 'fa',
'title' => 'درباره من',
'description' => 'من یک توسعه‌دهنده وب با بیش از 10 سال تجربه در ایجاد برنامه‌های وب پویا و کاربرمحور هستم. با تخصص در React و Next.js، راه‌حل‌های مقیاس‌پذیری ایجاد می‌کنم که عملکرد و تجربه کاربری را بهبود می‌بخشند. من از حل چالش‌های پیچیده لذت می‌برم، از بهبود سیستم‌های قدیمی گرفته تا توسعه برنامه‌های جدید. تمرکز من بر توسعه فرانت‌اند و یکپارچه‌سازی بی‌دردسر با بک‌اند به من این امکان را می‌دهد که نتایج نوآورانه‌ای ارائه دهم و هم‌زمان با روندهای صنعت به‌روز باشم.',
]);
// ایجاد رکوردهای Skill و ترجمه‌های انگلیسی و فارسی
// HTML & CSS (SASS, Responsive Design)
$htmlSkill = Skill::create([
'about_me_id' => $aboutMe->id,
'image' => '/images/frontend.png',
'percentage' => 95,
'link' => 'http://example.com/frontend',
]);
SkillTranslation::create([
'skill_id' => $htmlSkill->id,
'locale' => 'en',
'title' => 'HTML & CSS (SASS, Responsive Design)',
'description' => 'Skilled in HTML5, CSS3, including SASS for modular and maintainable stylesheets. Experienced in building responsive web designs.',
]);
SkillTranslation::create([
'skill_id' => $htmlSkill->id,
'locale' => 'fa',
'title' => 'HTML و CSS (SASS، طراحی واکنش‌گرا)',
'description' => 'مهارت در HTML5، CSS3، شامل SASS برای ساخت استایل‌های مدولار و قابل نگهداری. تجربه در طراحی وب‌سایت‌های واکنش‌گرا.',
]);
// React.js and Next.js Development
$reactSkill = Skill::create([
'about_me_id' => $aboutMe->id,
'image' => '/images/backend.png',
'percentage' => 90,
'link' => 'http://example.com/backend',
]);
SkillTranslation::create([
'skill_id' => $reactSkill->id,
'locale' => 'en',
'title' => 'React.js and Next.js Development',
'description' => 'Extensive experience in React.js and Next.js for building scalable and performant web applications.',
]);
SkillTranslation::create([
'skill_id' => $reactSkill->id,
'locale' => 'fa',
'title' => 'توسعه React.js و Next.js',
'description' => 'تجربه گسترده در توسعه React.js و Next.js برای ساخت برنامه‌های وب مقیاس‌پذیر و پرکاربرد.',
]);
// Backend Development (RESTful APIs, Laravel)
$backendSkill = Skill::create([
'about_me_id' => $aboutMe->id,
'image' => '/images/ui.png',
'percentage' => 85,
'link' => 'http://example.com/ui',
]);
SkillTranslation::create([
'skill_id' => $backendSkill->id,
'locale' => 'en',
'title' => 'Backend Development (RESTful APIs, Laravel)',
'description' => 'Proficient in backend development, building robust RESTful APIs using Laravel and other technologies.',
]);
SkillTranslation::create([
'skill_id' => $backendSkill->id,
'locale' => 'fa',
'title' => 'توسعه بک‌اند (APIهای RESTful، لاراول)',
'description' => 'تسلط به توسعه بک‌اند و ساخت APIهای RESTful با استفاده از لاراول و دیگر تکنولوژی‌ها.',
]);
// WordPress Development and Customization
$wordpressSkill = Skill::create([
'about_me_id' => $aboutMe->id,
'image' => '/images/ux.png',
'percentage' => 90,
'link' => 'http://example.com/ux',
]);
SkillTranslation::create([
'skill_id' => $wordpressSkill->id,
'locale' => 'en',
'title' => 'WordPress Development and Customization',
'description' => 'Skilled in WordPress development, including theme customization and plugin development.',
]);
SkillTranslation::create([
'skill_id' => $wordpressSkill->id,
'locale' => 'fa',
'title' => 'توسعه و شخصی‌سازی وردپرس',
'description' => 'مهارت در توسعه وردپرس، شامل شخصی‌سازی قالب‌ها و توسعه افزونه‌ها.',
]);
// Version Control (Git, GitHub)
$gitSkill = Skill::create([
'about_me_id' => $aboutMe->id,
'image' => '/images/ux.png',
'percentage' => 80,
'link' => 'http://example.com/ux',
]);
SkillTranslation::create([
'skill_id' => $gitSkill->id,
'locale' => 'en',
'title' => 'Version Control (Git, GitHub)',
'description' => 'Experienced in version control using Git and GitHub for managing codebases and collaboration.',
]);
SkillTranslation::create([
'skill_id' => $gitSkill->id,
'locale' => 'fa',
'title' => 'کنترل نسخه (Git, GitHub)',
'description' => 'تجربه در کنترل نسخه با استفاده از Git و GitHub برای مدیریت کدها و همکاری تیمی.',
]);
}
}

View File

@ -0,0 +1,41 @@
<?php
namespace Database\Seeders\Website;
use Illuminate\Database\Seeder;
use App\Models\Website\ProjectCategory;
use App\Models\Website\ProjectCategoryTranslation;
class ProjectCategorySeeder extends Seeder
{
public function run()
{
$categories = [
['fa' => 'طراحی اپلیکیشن', 'en' => 'App Design'],
['fa' => 'فرانت اند', 'en' => 'Front End'],
['fa' => 'بک اند', 'en' => 'Backend'],
['fa' => 'طراحی وب', 'en' => 'Web Design'],
['fa' => 'طراحی گرافیک', 'en' => 'Graphic Design'],
];
foreach ($categories as $key => $category) {
// ایجاد دسته‌بندی اصلی
$createdCategory = ProjectCategory::create(['image' => 'category' . ($key + 1) . '.jpg']);
// ایجاد ترجمه‌ها
ProjectCategoryTranslation::create([
'category_id' => $createdCategory->id,
'locale' => 'fa',
'title' => $category['fa'],
'description' => 'توضیحات ' . $category['fa'],
]);
ProjectCategoryTranslation::create([
'category_id' => $createdCategory->id,
'locale' => 'en',
'title' => $category['en'],
'description' => 'Description for ' . $category['en'],
]);
}
}
}

View File

@ -0,0 +1,46 @@
<?php
namespace Database\Seeders\Website;
use Illuminate\Database\Seeder;
use App\Models\Website\Project;
use App\Models\Website\ProjectTranslation;
use App\Models\Website\ProjectCategory;
class ProjectSeeder extends Seeder
{
public function run()
{
// دریافت تمام دسته‌بندی‌ها
$categories = ProjectCategory::all();
foreach ($categories as $category) {
// ایجاد تعداد تصادفی پروژه برای هر دسته‌بندی
$projectCount = rand(5, 10);
for ($i = 1; $i <= $projectCount; $i++) {
// ایجاد پروژه جدید
$project = Project::create([
'category_id' => $category->id,
'image1' => 'project' . $i . '_image1.jpg',
'image2' => 'project' . $i . '_image2.jpg'
]);
// ایجاد ترجمه‌ها
ProjectTranslation::create([
'project_id' => $project->id,
'locale' => 'fa',
'title' => 'پروژه ' . $i . ' - ' . $category->translations()->where('locale', 'fa')->first()->title,
'description' => 'توضیحات پروژه ' . $i . ' برای دسته‌بندی ' . $category->translations()->where('locale', 'fa')->first()->title,
]);
ProjectTranslation::create([
'project_id' => $project->id,
'locale' => 'en',
'title' => 'Project ' . $i . ' - ' . $category->translations()->where('locale', 'en')->first()->title,
'description' => 'Description for project ' . $i . ' in category ' . $category->translations()->where('locale', 'en')->first()->title,
]);
}
}
}
}

View File

@ -0,0 +1,96 @@
<?php
namespace Database\Seeders\Website;
use Illuminate\Database\Seeder;
use App\Models\Website\Service;
use App\Models\Website\ServiceTranslation;
class ServiceSeeder extends Seeder
{
/**
* Run the database seeds.
*/
public function run()
{
// خدمات با ترجمه‌های فارسی
$services = [
[
'imageSrc' => '/images/ui-ux-vector.svg',
'translations' => [
[
'locale' => 'fa',
'title' => 'توسعه وب سفارشی',
'description' => 'ما برنامه‌های وب سفارشی را ایجاد می‌کنیم که نیازهای خاص کسب‌وکار شما را برآورده می‌سازد و از آخرین تکنولوژی‌ها برای عملکرد بهینه استفاده می‌کند.',
],
[
'locale' => 'en',
'title' => 'Custom Web Development',
'description' => 'We create tailored web applications that meet your unique business requirements, utilizing the latest technologies for optimal performance.',
],
],
],
[
'imageSrc' => '/images/web-design-vector.svg',
'translations' => [
[
'locale' => 'fa',
'title' => 'توسعه فرانت‌اند',
'description' => 'خدمات توسعه فرانت‌اند ما بر روی ایجاد رابط‌های کاربری جذاب و پاسخگو تمرکز دارد که تجربه کاربری را در تمامی دستگاه‌ها بهبود می‌بخشد.',
],
[
'locale' => 'en',
'title' => 'Frontend Development',
'description' => 'Our frontend development services focus on crafting engaging, responsive user interfaces that enhance user experience across all devices.',
],
],
],
[
'imageSrc' => '/images/app-design-vector.svg',
'translations' => [
[
'locale' => 'fa',
'title' => 'توسعه بک‌اند',
'description' => 'ما راه‌حل‌های قابل اعتماد توسعه بک‌اند را ارائه می‌دهیم و معماری‌های سروری و APIهای قوی را برای اطمینان از عملکرد روان و ایمن برنامه ایجاد می‌کنیم.',
],
[
'locale' => 'en',
'title' => 'Backend Development',
'description' => 'We provide reliable backend development solutions, building robust server-side architectures and APIs to ensure smooth and secure application functionality.',
],
],
],
[
'imageSrc' => '/images/graphic-design-vector.svg',
'translations' => [
[
'locale' => 'fa',
'title' => 'نگهداری و پشتیبانی وب‌سایت',
'description' => 'خدمات نگهداری و پشتیبانی مداوم ما وب‌سایت شما را به‌روز، امن و با بهترین عملکرد نگه می‌دارد تا شما بتوانید بر روی کسب‌وکار اصلی خود تمرکز کنید.',
],
[
'locale' => 'en',
'title' => 'Website Maintenance and Support',
'description' => 'Our ongoing maintenance and support services keep your website updated, secure, and performing at its best, allowing you to focus on your core business.',
],
],
],
];
// ذخیره خدمات و ترجمه‌ها
foreach ($services as $serviceData) {
$service = Service::create([
'imageSrc' => $serviceData['imageSrc'],
]);
foreach ($serviceData['translations'] as $translation) {
ServiceTranslation::create([
'service_id' => $service->id,
'locale' => $translation['locale'],
'title' => $translation['title'],
'description' => $translation['description'],
]);
}
}
}
}

BIN
public/images/parsa2.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 MiB

BIN
public/images/parsa21.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 113 KiB

BIN
public/images/parsa22.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 71 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 86 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 307 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 97 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 58 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 57 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 54 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 130 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 33 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 72 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 54 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 110 KiB

View File

@ -4,7 +4,7 @@
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Laravel</title>
<title>Laravel v1</title>
<!-- Fonts -->
<link rel="preconnect" href="https://fonts.bunny.net">

View File

@ -2,17 +2,44 @@
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Route;
use App\Http\Controllers\ProjectController;
use App\Http\Controllers\AboutMeController;
use App\Http\Controllers\SkillController;
use App\Http\Controllers\ServiceController;
use App\Http\Controllers\Blog\CategoryController;
use App\Http\Controllers\Blog\HomeController;
use App\Http\Controllers\Blog\PostController;
use App\Http\Controllers\Blog\TagController;
// use App\Http\Controllers\SkillController;
use App\Http\Controllers\Website\ServiceController;
use App\Http\Controllers\Website\AboutMeController;
use App\Http\Controllers\Website\ProjectController;
Route::get('/user', function (Request $request) {
return $request->user();
})->middleware('auth:sanctum');
// Route::resource('projects', ProjectController::class);
Route::resource('projects', ProjectController::class);
Route::resource('about-me', AboutMeController::class);
Route::resource('skills', SkillController::class);
Route::apiResource('services', ServiceController::class);
Route::apiResource('services', ServiceController::class);
Route::prefix('website')->group(function () {
Route::get('about-me/{id}/translation/{locale}', [AboutMeController::class, 'getTranslation']);
Route::get('services/{locale}', [ServiceController::class, 'index']); // مسیر جدید برای لیست خدمات با ترجمه
Route::get('services/{id}/translation/{locale}', [ServiceController::class, 'showTranslation']);
Route::group(['prefix' => 'projects'], function () {
Route::get('/translation/{locale}', [ProjectController::class, 'index']);
Route::get('/{id}/translation/{locale}', [ProjectController::class, 'show']);
Route::post('/', [ProjectController::class, 'store']);
Route::put('/{id}', [ProjectController::class, 'update']);
Route::delete('/{id}', [ProjectController::class, 'destroy']);
});
});
// مسیرهای بلاگ
Route::prefix('blog')->group(function () {
// پست‌ها
Route::apiResource('posts', PostController::class);
// دسته‌بندی‌ها
Route::apiResource('categories', CategoryController::class);
// تگ‌ها
Route::apiResource('tags', TagController::class);
// مسیر Homepage
Route::get('homepage', [HomeController::class, 'index']);
Route::get('categories/{slug}/posts', [CategoryController::class, 'getCategoryWithPosts']);
});

0
storage/app/.gitignore vendored Normal file → Executable file
View File

0
storage/app/private/.gitignore vendored Normal file → Executable file
View File

0
storage/app/public/.gitignore vendored Normal file → Executable file
View File

0
storage/framework/.gitignore vendored Normal file → Executable file
View File

0
storage/framework/cache/.gitignore vendored Normal file → Executable file
View File

0
storage/framework/cache/data/.gitignore vendored Normal file → Executable file
View File

0
storage/framework/sessions/.gitignore vendored Normal file → Executable file
View File

0
storage/framework/testing/.gitignore vendored Normal file → Executable file
View File

0
storage/framework/views/.gitignore vendored Normal file → Executable file
View File

0
storage/logs/.gitignore vendored Normal file → Executable file
View File