Full-Featured Next.js 14 پروژه با الهام از ساختار MVC Laravel

در این مقاله ، ما چگونگی ساخت یک پروژه کامل بعدی را بررسی خواهیم کرد. Laravel یک چارچوب قدرتمند PHP است که از الگوی MVC پیروی می کند و روشی تمیز و سازمان یافته برای ساخت برنامه های وب ارائه می دهد. از طرف دیگر ، یک چارچوب React است که عملکردی از قبیل رندر سمت سرور (SSR) ، تولید سایت استاتیک (SSG) و API را امکان پذیر می کند و آن را به یک انتخاب عالی برای ساخت برنامه های وب مدرن تبدیل می کند.
ما با بررسی ساختار دایرکتوری پروژه Laravel ارائه می دهیم ، و سپس آن را با استفاده از پروژه بعدی. js 14 تبدیل خواهیم کرد روتر برنامه، اطمینان از اینکه هر ویژگی و مؤلفه در پروژه Laravel دارای یک معادل در پروژه بعدی است. ما همچنین نحوه استفاده را پوشش خواهیم داد غوغا برای mongoDb و پریسما برای MySQL ، ارائه نمونه های کد در طول مسیر.
ساختار دایرکتوری پروژه لاراول
در اینجا ساختار دایرکتوری پروژه Laravel ارائه شده است:
📂 laravel-advanced-project/
│── 📂 app/
│ │── 📂 Console/
│ │ │── Kernel.php
│ │── 📂 Events/
│ │ │── PostCreated.php
│ │ │── UserRegistered.php
│ │── 📂 Exceptions/
│ │ │── Handler.php
│ │── 📂 Http/
│ │ │── 📂 Controllers/
│ │ │ │── 📂 API/
│ │ │ │ │── PostController.php
│ │ │ │ │── UserController.php
│ │ │ │── 📂 Web/
│ │ │ │ │── HomeController.php
│ │ │ │ │── ProfileController.php
│ │ │── 📂 Middleware/
│ │ │ │── Authenticate.php
│ │ │ │── RedirectIfAuthenticated.php
│ │ │── 📂 Requests/
│ │ │ │── UserRequest.php
│ │ │ │── PostRequest.php
│ │── 📂 Models/
│ │ │── User.php
│ │ │── Post.php
│ │ │── Comment.php
│ │── 📂 Notifications/
│ │ │── NewCommentNotification.php
│ │── 📂 Policies/
│ │ │── PostPolicy.php
│ │ │── CommentPolicy.php
│ │── 📂 Providers/
│ │ │── AppServiceProvider.php
│ │ │── AuthServiceProvider.php
│ │ │── EventServiceProvider.php
│ │── 📂 Services/
│ │ │── UserService.php
│ │ │── PostService.php
│ │── 📂 Traits/
│ │ │── ApiResponse.php
│── 📂 bootstrap/
│ │── app.php
│── 📂 config/
│ │── app.php
│ │── auth.php
│ │── database.php
│── 📂 database/
│ │── 📂 factories/
│ │ │── UserFactory.php
│ │ │── PostFactory.php
│ │── 📂 migrations/
│ │ │── 2024_01_01_000000_create_users_table.php
│ │ │── 2024_01_01_000001_create_posts_table.php
│ │ │── 2024_01_01_000002_create_comments_table.php
│ │── 📂 seeders/
│ │ │── DatabaseSeeder.php
│ │ │── UserSeeder.php
│ │ │── PostSeeder.php
│── 📂 lang/
│ │── 📂 en/
│ │ │── auth.php
│ │ │── validation.php
│── 📂 public/
│ │── 📂 css/
│ │ │── app.css
│ │── 📂 js/
│ │ │── app.js
│ │── 📂 images/
│ │── index.php
│── 📂 resources/
│ │── 📂 views/
│ │ │── 📂 layouts/
│ │ │ │── app.blade.php
│ │ │── 📂 users/
│ │ │ │── index.blade.php
│ │ │ │── show.blade.php
│ │ │── 📂 posts/
│ │ │ │── index.blade.php
│ │ │ │── show.blade.php
│ │── 📂 js/
│ │ │── app.js
│ │── 📂 sass/
│ │ │── app.scss
│── 📂 routes/
│ │── api.php
│ │── web.php
│── 📂 storage/
│ │── 📂 app/
│ │ │── uploads/
│ │── 📂 logs/
│ │ │── laravel.log
│── 📂 tests/
│ │── 📂 Feature/
│ │ │── UserTest.php
│ │ │── PostTest.php
│ │── 📂 Unit/
│ │ │── UserServiceTest.php
│ │ │── PostServiceTest.php
│── .env
│── .gitignore
│── artisan
│── composer.json
│── package.json
│── phpunit.xml
│── README.md
│── webpack.mix.js
NEXT.JS 14 ساختار دایرکتوری پروژه (با استفاده از روتر برنامه)
حال ، بیایید ساختار پروژه Laravel را به یک پروژه Next.JS 14 با استفاده از روتر برنامهبشر ما پروژه Next.js را به شکلی سازماندهی می کنیم که ساختار لاراول را آینه می دهد ، و اطمینان حاصل می کند که هر مؤلفه در پروژه بعدی معادل دارد.
📂 nextjs-advanced-project/
│── 📂 app/
│ │── 📂 api/
│ │ │── 📂 posts/
│ │ │ │── route.js
│ │ │── 📂 users/
│ │ │ │── route.js
│ │── 📂 lib/
│ │ │── 📂 events/
│ │ │ │── postCreated.js
│ │ │ │── userRegistered.js
│ │ │── 📂 middleware/
│ │ │ │── authenticate.js
│ │ │ │── redirectIfAuthenticated.js
│ │ │── 📂 models/
│ │ │ │── User.js
│ │ │ │── Post.js
│ │ │ │── Comment.js
│ │ │── 📂 services/
│ │ │ │── userService.js
│ │ │ │── postService.js
│ │ │── 📂 utils/
│ │ │ │── apiResponse.js
│ │── 📂 middleware/
│ │ │── authMiddleware.js
│ │── 📂 components/
│ │ │── 📂 layouts/
│ │ │ │── AppLayout.jsx
│ │ │── 📂 users/
│ │ │ │── UserList.jsx
│ │ │ │── UserProfile.jsx
│ │ │── 📂 posts/
│ │ │ │── PostList.jsx
│ │ │ │── PostDetail.jsx
│ │── 📂 pages/
│ │ │── 📂 users/
│ │ │ │── page.jsx
│ │ │ │── [id]/
│ │ │ │ │── page.jsx
│ │ │── 📂 posts/
│ │ │ │── page.jsx
│ │ │ │── [id]/
│ │ │ │ │── page.jsx
│ │ │── 📂 profile/
│ │ │ │── page.jsx
│ │ │── 📂 home/
│ │ │ │── page.jsx
│── 📂 config/
│ │── app.js
│ │── auth.js
│ │── database.js
│── 📂 database/
│ │── 📂 migrations/
│ │ │── 2024_01_01_000000_create_users_table.js
│ │ │── 2024_01_01_000001_create_posts_table.js
│ │ │── 2024_01_01_000002_create_comments_table.js
│ │── 📂 seeders/
│ │ │── databaseSeeder.js
│ │ │── userSeeder.js
│ │ │── postSeeder.js
│── 📂 public/
│ │── 📂 css/
│ │ │── app.css
│ │── 📂 js/
│ │ │── app.js
│ │── 📂 images/
│── 📂 styles/
│ │── globals.css
│── 📂 tests/
│ │── 📂 feature/
│ │ │── user.test.js
│ │ │── post.test.js
│ │── 📂 unit/
│ │ │── userService.test.js
│ │ │── postService.test.js
│── .env
│── .gitignore
│── package.json
│── README.md
│── next.config.js
next.js 14 پروژه: اجرای کامل
ما اکنون می گذرانیم هر دایرکتوری و پرونده در بعدی. 14 ساختار پروژه و اجرای رمز کامل برای همه چیز این شامل:
- مسیرهای API (با استفاده از روتر برنامه Next.js)
- مدل (استفاده از Mongoose برای MongoDB و Prisma برای MySQL)
- خدمات (منطق تجارت)
- ظروف میانبر (احراز هویت ، مجوز و غیره)
- اجزای (اجزای UI قابل استفاده مجدد)
- صفحات (با استفاده از روتر برنامه Next.js)
- وقایع (معماری رویداد محور)
- سود (توابع ابزار مانند پاسخ API)
- مهاجرت پایگاه داده و بذر
- تست (تست های واحد و ویژگی)
- پیکربندی محیط
- استایل (CSS و سبک های جهانی)
بیایید شروع کنیم!
1 مسیرهای API
در Next.JS 14 ، مسیرهای API در app/api/
دایرکتوری هر مسیر با یک منبع خاص مطابقت دارد (به عنوان مثال ، کاربران ، پست ها).
app/api/users/route.js
import { NextResponse } from 'next/server';
import { PrismaClient } from '@prisma/client';
const prisma = new PrismaClient();
// GET /api/users - Fetch all users
export async function GET() {
try {
const users = await prisma.user.findMany();
return NextResponse.json(users);
} catch (error) {
return NextResponse.json({ error: 'Failed to fetch users' }, { status: 500 });
}
}
// POST /api/users - Create a new user
export async function POST(request) {
try {
const data = await request.json();
const user = await prisma.user.create({ data });
return NextResponse.json(user, { status: 201 });
} catch (error) {
return NextResponse.json({ error: 'Failed to create user' }, { status: 500 });
}
}
app/api/posts/route.js
import { NextResponse } from 'next/server';
import { PrismaClient } from '@prisma/client';
const prisma = new PrismaClient();
// GET /api/posts - Fetch all posts
export async function GET() {
try {
const posts = await prisma.post.findMany({
include: { author: true, comments: true },
});
return NextResponse.json(posts);
} catch (error) {
return NextResponse.json({ error: 'Failed to fetch posts' }, { status: 500 });
}
}
// POST /api/posts - Create a new post
export async function POST(request) {
try {
const data = await request.json();
const post = await prisma.post.create({ data });
return NextResponse.json(post, { status: 201 });
} catch (error) {
return NextResponse.json({ error: 'Failed to create post' }, { status: 500 });
}
}
2 مدل
ما استفاده خواهیم کرد پریسما برای mysql و غوغا برای MongoDB در اینجا نحوه تعریف مدل ها برای هر دو آورده شده است.
مدل های Prisma (MySQL)
در prisma/schema.prisma
پرونده:
model User {
id Int @id @default(autoincrement())
name String
email String @unique
password String
posts Post[]
comments Comment[]
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
}
model Post {
id Int @id @default(autoincrement())
title String
content String
authorId Int
author User @relation(fields: [authorId], references: [id])
comments Comment[]
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
}
model Comment {
id Int @id @default(autoincrement())
content String
postId Int
post Post @relation(fields: [postId], references: [id])
authorId Int
author User @relation(fields: [authorId], references: [id])
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
}
مدل های Mongoose (MongoDB)
در app/lib/models/
دایرکتوری:
app/lib/models/User.js
import mongoose from 'mongoose';
const userSchema = new mongoose.Schema({
name: { type: String, required: true },
email: { type: String, required: true, unique: true },
password: { type: String, required: true },
posts: [{ type: mongoose.Schema.Types.ObjectId, ref: 'Post' }],
comments: [{ type: mongoose.Schema.Types.ObjectId, ref: 'Comment' }],
}, { timestamps: true });
export default mongoose.models.User || mongoose.model('User', userSchema);
app/lib/models/Post.js
import mongoose from 'mongoose';
const postSchema = new mongoose.Schema({
title: { type: String, required: true },
content: { type: String, required: true },
author: { type: mongoose.Schema.Types.ObjectId, ref: 'User', required: true },
comments: [{ type: mongoose.Schema.Types.ObjectId, ref: 'Comment' }],
}, { timestamps: true });
export default mongoose.models.Post || mongoose.model('Post', postSchema);
3 خدمات
خدمات حاوی منطق تجارت برای برنامه شما هستند. بیایید خدمات را برای کاربران و پست ها ایجاد کنیم.
app/lib/services/userService.js
import prisma from '@/lib/prisma';
export const createUser = async (userData) => {
return await prisma.user.create({ data: userData });
};
export const getUserById = async (userId) => {
return await prisma.user.findUnique({ where: { id: userId } });
};
export const getAllUsers = async () => {
return await prisma.user.findMany();
};
app/lib/services/postService.js
import prisma from '@/lib/prisma';
export const createPost = async (postData) => {
return await prisma.post.create({ data: postData });
};
export const getPostById = async (postId) => {
return await prisma.post.findUnique({ where: { id: postId }, include: { author: true } });
};
export const getAllPosts = async () => {
return await prisma.post.findMany({ include: { author: true } });
};
4 ظروف میانبر
Middleware برای تأیید اعتبار ، مجوز و سایر تغییرات درخواست/پاسخ استفاده می شود.
app/middleware/authMiddleware.js
import { NextResponse } from 'next/server';
import jwt from 'jsonwebtoken';
export function middleware(request) {
const token = request.cookies.get('token')?.value;
if (!token) {
return NextResponse.redirect('/login');
}
try {
jwt.verify(token, process.env.JWT_SECRET);
return NextResponse.next();
} catch (error) {
return NextResponse.redirect('/login');
}
}
5 اجزای
مؤلفه ها عناصر UI قابل استفاده مجدد هستند. بیایید یک طرح و برخی از مؤلفه های کاربر/پست ایجاد کنیم.
app/components/layouts/AppLayout.jsx
export default function AppLayout({ children }) {
return (
<div>
<header>Header</header>
<main>{children}</main>
<footer>Footer</footer>
</div>
);
}
app/components/users/UserList.jsx
export default function UserList({ users }) {
return (
<ul>
{users.map((user) => (
<li key={user.id}>{user.name}</li>
))}
</ul>
);
}
6 صفحات
صفحات در app/pages/
دایرکتوری بیایید صفحاتی را برای کاربران و پست ها ایجاد کنیم.
app/pages/users/page.jsx
import UserList from '@/components/users/UserList';
import { getAllUsers } from '@/lib/services/userService';
export default async function UsersPage() {
const users = await getAllUsers();
return (
<div>
<h1>Users</h1>
<UserList users={users} />
</div>
);
}
app/pages/posts/page.jsx
import PostList from '@/components/posts/PostList';
import { getAllPosts } from '@/lib/services/postService';
export default async function PostsPage() {
const posts = await getAllPosts();
return (
<div>
<h1>Posts</h1>
<PostList posts={posts} />
</div>
);
}
7 وقایع
از رویدادها برای معماری رویداد محور استفاده می شود. بیایید یک رویداد برای ثبت نام کاربر ایجاد کنیم.
app/lib/events/userRegistered.js
import { EventEmitter } from 'events';
class UserRegistered extends EventEmitter {
constructor() {
super();
this.eventName = 'UserRegistered';
}
emitEvent(user) {
this.emit(this.eventName, user);
}
}
export default new UserRegistered();
8 سود
UTIL ها شامل توابع ابزار مانند پاسخ های API هستند.
app/lib/utils/apiResponse.js
export const successResponse = (res, data, status = 200) => {
return res.status(status).json({ success: true, data });
};
export const errorResponse = (res, message, status = 500) => {
return res.status(status).json({ success: false, error: message });
};
9 مهاجرت پایگاه داده و بذر
مهاجرت های Prisma
دستور زیر را برای ایجاد و اعمال مهاجرت اجرا کنید:
npx prisma migrate dev --name init
بذرکار
در prisma/seed.js
پرونده:
import { PrismaClient } from '@prisma/client';
const prisma = new PrismaClient();
async function main() {
await prisma.user.create({
data: {
name: 'John Doe',
email: 'john@example.com',
password: 'password123',
},
});
}
main()
.catch((e) => {
console.error(e);
process.exit(1);
})
.finally(async () => {
await prisma.$disconnect();
});
10 تست
تست های واحد
tests/unit/userService.test.js
import { createUser, getUserById } from '@/lib/services/userService';
describe('UserService', () => {
it('should create a new user', async () => {
const user = await createUser({ name: 'John Doe', email: 'john@example.com', password: 'password123' });
expect(user).toHaveProperty('id');
});
});
11 پیکربندی محیط
.env
DATABASE_URL=mysql://user:password@localhost:3306/nextjs-advanced-project
JWT_SECRET=your_jwt_secret
12 استایل
styles/globals.css
body {
font-family: Arial, sans-serif;
}
header {
background-color: #333;
color: white;
padding: 1rem;
}
footer {
background-color: #333;
color: white;
padding: 1rem;
text-align: center;
}
پایان
این راهنمای جامع هر جنبه ای از ساخت a را پوشش داده است next.js 14 پروژه با الهام از ساختار MVC لاراول. ما پیاده سازی کرده ایم مسیرهای APIبا مدلبا خدماتبا ظروف میانبربا اجزایبا صفحاتبا وقایعبا سودبا مهاجرت پایگاه دادهبا تستوت استایلبشر با دنبال کردن این ساختار ، می توانید یک مقیاس پذیر و حفظ برنامه بعدی