لو إنت شغال بـ Node.js وبتتعامل مع قواعد بيانات زي MySQL أو PostgreSQL أو SQLite، فأكيد قابلتك مشكلة كتابة استعلامات SQL كتير ومعقدة. هنا بييجي دور Prisma، وهي واحدة من أقوى الأدوات اللي بتسهل التعامل مع قواعد البيانات داخل تطبيقات Node.js بطريقة نظيفة وسريعة وآمنة.
في المقال ده هنتعرف على Prisma في Node.js خطوة بخطوة، بداية من التثبيت، مرورًا بإنشاء الـ Models، وتشغيل الـ Migration، لحد بناء API كامل باستخدام Express و Prisma.
يعني إيه Prisma؟
Prisma هي أداة ORM حديثة بتخليك تتعامل مع قاعدة البيانات باستخدام JavaScript أو TypeScript بدل ما تكتب SQL بشكل مباشر.
يعني بدل ما تكتب استعلامات SQL طويلة ومعقدة، تقدر تستخدم Prisma Client وتتعامل مع البيانات من خلال كود بسيط وواضح.
Prisma بتدعم أكتر من نوع قاعدة بيانات، زي:
- MySQL
- PostgreSQL
- SQLite
- SQL Server
- MongoDB
مميزات Prisma في Node.js
Prisma مش مجرد ORM عادي، لكنها Toolkit كاملة بتوفرلك تجربة مريحة جدًا أثناء التعامل مع قواعد البيانات.
- كتابة كود أنظف وأسهل من SQL التقليدي
- دعم قوي لـ TypeScript
- Auto Completion ممتاز داخل VSCode
- إدارة العلاقات بين الجداول بسهولة
- نظام Migration لتنظيم تغييرات قاعدة البيانات
- تقليل الأخطاء أثناء كتابة الاستعلامات
تثبيت Prisma داخل مشروع Node.js
أول حاجة لازم يكون عندك مشروع Node.js جاهز. لو لسه معندكش مشروع، تقدر تعمل واحد بالأوامر التالية:
mkdir prisma-node-app
cd prisma-node-app
npm init -y
بعد كده هنثبت Express عشان نعمل API:
npm install express
دلوقتي نثبت Prisma:
npm install prisma --save-dev
npm install @prisma/client
بعد التثبيت، نعمل تهيئة لـ Prisma داخل المشروع:
npx prisma init
الأمر ده هيعمل فولدر اسمه prisma وداخله ملف مهم جدًا اسمه:
prisma/schema.prisma
وكمان هيعمل ملف .env اللي هنحط فيه رابط الاتصال بقاعدة البيانات.
الاتصال بقاعدة البيانات باستخدام DATABASE_URL
داخل ملف .env هنضيف رابط الاتصال بقاعدة البيانات.
مثال على الاتصال بقاعدة بيانات MySQL:
DATABASE_URL="mysql://root:Aa123456!@localhost:3306/newdb"
شرح الرابط:
mysql: نوع قاعدة البياناتroot: اسم المستخدمAa123456!: كلمة المرورlocalhost: السيرفر المحلي3306: بورت MySQLnewdb: اسم قاعدة البيانات
إعداد ملف schema.prisma
ملف schema.prisma هو المكان اللي بنعرف فيه الجداول والعلاقات بينهم.
مثال على ملف كامل يحتوي على جدول المستخدمين وجدول المقالات أو المنشورات:
generator client {
provider = "prisma-client-js"
output = "../generated/prisma"
}
datasource db {
provider = "mysql"
url = env("DATABASE_URL")
}
model User {
id Int @id @default(autoincrement())
name String
email String @unique
posts Post[]
}
model Post {
id Int @id @default(autoincrement())
title String
content String?
author User @relation(fields: [authorId], references: [id])
authorId Int
}
شرح Models داخل Prisma
في المثال السابق عندنا جدولين:
جدول User
model User {
id Int @id @default(autoincrement())
name String
email String @unique
posts Post[]
}
الجدول ده بيحتوي على:
id: رقم المستخدم وبيزيد تلقائيًاname: اسم المستخدمemail: البريد الإلكتروني ولازم يكون غير مكررposts: علاقة بين المستخدم والمنشورات الخاصة به
جدول Post
model Post {
id Int @id @default(autoincrement())
title String
content String?
author User @relation(fields: [authorId], references: [id])
authorId Int
}
الجدول ده بيحتوي على:
id: رقم المنشورtitle: عنوان المنشورcontent: محتوى المنشور وهو اختياري بسبب علامة?authorId: رقم المستخدم صاحب المنشورauthor: العلاقة بين المنشور والمستخدم
تشغيل Migration وإنشاء الجداول
بعد ما تكتب الـ Models داخل ملف schema.prisma، لازم تعمل Migration عشان Prisma تنشئ الجداول داخل قاعدة البيانات.
npx prisma migrate dev --name init
الأمر ده بيعمل 3 حاجات مهمة:
- ينشئ ملفات Migration
- ينشئ الجداول داخل قاعدة البيانات
- يجهز Prisma Client للاستخدام داخل المشروع
ولو عدلت في ملف schema.prisma بعد كده، شغل الأمر التالي:
npx prisma generate
إنشاء ملف السيرفر باستخدام Express و Prisma
دلوقتي هننشئ ملف اسمه index.js ونبدأ نكتب API كامل للتعامل مع المستخدمين والمنشورات.
const express = require("express");
const { PrismaClient } = require("./generated/prisma");
const app = express();
app.use(express.json());
const prisma = new PrismaClient();
const PORT = 3000;
app.listen(PORT, () => {
console.log(`الخادم يعمل على المنفذ ${PORT}`);
});
في الكود السابق عملنا:
- استدعاء Express
- استدعاء PrismaClient
- تشغيل JSON Middleware
- إنشاء Instance من Prisma
- تشغيل السيرفر على بورت 3000
إنشاء مستخدم جديد باستخدام Prisma
هنضيف Route لإنشاء مستخدم جديد داخل قاعدة البيانات.
app.post("/user", async (req, res) => {
const { name, email } = req.body;
if (!name || !email) {
return res.status(400).json({
error: "الاسم والبريد الإلكتروني مطلوبان"
});
}
try {
const user = await prisma.user.create({
data: {
name,
email,
},
});
res.status(201).json(user);
} catch (error) {
if (error.code === "P2002") {
return res.status(409).json({
error: "البريد الإلكتروني مكرر"
});
}
res.status(500).json({
error: "خطأ في إنشاء المستخدم"
});
}
});
في الكود ده بنعمل الآتي:
- بنستقبل
nameوemailمن body - بنتأكد إن البيانات موجودة
- بنستخدم
prisma.user.createلإنشاء مستخدم جديد - لو البريد الإلكتروني مكرر، Prisma بترجع error code اسمه
P2002
جلب المستخدمين والبحث بالاسم
ممكن نعمل Route للبحث عن المستخدمين باستخدام الاسم.
app.get("/user", async (req, res) => {
const { name } = req.body;
try {
const user = await prisma.user.findMany({
where: {
name: {
contains: name,
},
},
});
res.status(200).json(user);
} catch (error) {
res.status(500).json({
error: "خطأ في جلب المستخدمين"
});
}
});
استخدمنا هنا findMany لأنها بترجع أكتر من مستخدم.
واستخدمنا contains عشان نبحث عن أي اسم يحتوي على النص المرسل.
إنشاء منشور جديد وربطه بالمستخدم
دلوقتي هنضيف Route لإنشاء منشور جديد، ولازم المنشور يكون مرتبط بمستخدم موجود بالفعل.
app.post("/post", async (req, res) => {
const { title, content, authorId } = req.body;
if (!title || !authorId) {
return res.status(400).json({
error: "العنوان ورقم المؤلف مطلوبان"
});
}
try {
const user = await prisma.user.findUnique({
where: {
id: authorId,
},
});
if (!user) {
return res.status(404).json({
error: "المستخدم غير موجود"
});
}
const newPost = await prisma.post.create({
data: {
title,
content: content || null,
authorId,
},
});
res.status(201).json({
message: "تم إنشاء المنشور بنجاح",
post: newPost,
});
} catch (error) {
console.error("خطأ في إنشاء المنشور:", error);
res.status(500).json({
error: "حدث خطأ داخلي في الخادم"
});
}
});
في المثال ده عملنا خطوة مهمة جدًا، وهي التحقق من وجود المستخدم قبل إنشاء المنشور.
وده بيمنع إننا نضيف Post مرتبط بـ User غير موجود داخل قاعدة البيانات.
جلب المنشورات مع بيانات المؤلف
Prisma بتسهل جدًا جلب البيانات المرتبطة ببعض.
مثلاً لو عايز تجيب كل المنشورات ومعاها بيانات المستخدم صاحب كل منشور، تقدر تستخدم include.
app.get("/posts", async (req, res) => {
try {
const posts = await prisma.post.findMany({
include: {
author: true,
},
});
res.json(posts);
} catch (error) {
console.error("خطأ في جلب المنشورات:", error);
res.status(500).json({
error: "فشل جلب البيانات"
});
}
});
استخدام include هنا معناه إن Prisma هترجع المنشورات ومعاها بيانات المؤلف المرتبط بكل منشور.
المثال الكامل لاستخدام Prisma مع Node.js
const express = require("express");
const { PrismaClient } = require("./generated/prisma");
const app = express();
app.use(express.json());
const prisma = new PrismaClient();
app.post("/post", async (req, res) => {
const { title, content, authorId } = req.body;
if (!title || !authorId) {
return res.status(400).json({
error: "العنوان ورقم المؤلف مطلوبان"
});
}
try {
const user = await prisma.user.findUnique({
where: {
id: authorId,
},
});
if (!user) {
return res.status(404).json({
error: "المستخدم غير موجود"
});
}
const newPost = await prisma.post.create({
data: {
title,
content: content || null,
authorId,
},
});
res.status(201).json({
message: "تم إنشاء المنشور بنجاح",
post: newPost,
});
} catch (error) {
console.error("خطأ في إنشاء المنشور:", error);
res.status(500).json({
error: "حدث خطأ داخلي في الخادم"
});
}
});
app.get("/posts", async (req, res) => {
try {
const posts = await prisma.post.findMany({
include: {
author: true,
},
});
res.json(posts);
} catch (error) {
console.error("خطأ في جلب المنشورات:", error);
res.status(500).json({
error: "فشل جلب البيانات"
});
}
});
app.post("/user", async (req, res) => {
const { name, email } = req.body;
if (!name || !email) {
return res.status(400).json({
error: "الاسم والبريد الإلكتروني مطلوبان"
});
}
try {
const user = await prisma.user.create({
data: {
name,
email,
},
});
res.status(201).json(user);
} catch (error) {
if (error.code === "P2002") {
return res.status(409).json({
error: "البريد الإلكتروني مكرر"
});
}
res.status(500).json({
error: "خطأ في إنشاء المستخدم"
});
}
});
app.get("/user", async (req, res) => {
const { name } = req.body;
try {
const user = await prisma.user.findMany({
where: {
name: {
contains: name,
},
},
});
res.status(200).json(user);
} catch (error) {
res.status(500).json({
error: "خطأ في جلب المستخدمين"
});
}
});
const PORT = 3000;
app.listen(PORT, () => {
console.log(`الخادم يعمل على المنفذ ${PORT}`);
});
أهم أوامر Prisma التي هتحتاجها
دي مجموعة من أهم أوامر Prisma اللي هتستخدمها كتير أثناء الشغل:
npx prisma init
لتهيئة Prisma داخل المشروع.
npx prisma migrate dev --name init
لإنشاء Migration وتطبيق التغييرات على قاعدة البيانات.
npx prisma generate
لتوليد Prisma Client بعد تعديل ملف schema.
npx prisma studio
لفتح واجهة رسومية تقدر من خلالها تشوف وتعدل البيانات الموجودة في قاعدة البيانات.
استخدام Prisma Studio
واحدة من المميزات الجميلة في Prisma هي أداة Prisma Studio.
الأداة دي بتفتحلك واجهة بسيطة في المتصفح تقدر من خلالها تشوف الجداول والبيانات وتضيف أو تعدل أو تحذف Records بسهولة.
npx prisma studio
بعد تشغيل الأمر، هيفتح معاك رابط في المتصفح لإدارة البيانات بشكل مرئي.
إضافة Prisma Insider في VSCode
لو عايز تجربة أفضل أثناء كتابة ملفات Prisma داخل VSCode، تقدر تستخدم إضافة:
Prisma – Insider
الإضافة دي بتساعدك في:
- تنسيق ملفات
.prismaتلقائيًا - تكميل ذكي للكود
- اكتشاف الأخطاء أثناء الكتابة
- تحسين تجربة العمل مع Prisma داخل VSCode
وتقدر تضيف الإعدادات التالية داخل ملف settings.json في VSCode:
{
"[prisma]": {
"editor.defaultFormatter": "Prisma.prisma-insider",
"editor.formatOnSave": true
}
}
بعد كده أي ملف .prisma هيتفرمت تلقائيًا عند الحفظ.
الفرق بين Prisma وكتابة SQL مباشرة
| Prisma | SQL مباشر |
|---|---|
| كود أبسط وأسهل | استعلامات أطول |
| يدعم Type Safety | أخطاء أكثر أثناء الكتابة |
| إدارة العلاقات سهلة | تحتاج JOIN يدوي |
| Migration منظمة | تحتاج إدارة يدوية |
أفضل استخدامات Prisma
تقدر تستخدم Prisma في مشاريع كتير، زي:
- REST APIs باستخدام Express
- تطبيقات Next.js
- لوحات التحكم Admin Dashboards
- أنظمة تسجيل الدخول والمستخدمين
- المتاجر الإلكترونية
- تطبيقات إدارة المحتوى
نصائح مهمة عند استخدام Prisma
- متنساش تشغل
npx prisma generateبعد أي تعديل في schema - استخدم
@uniqueمع الحقول اللي مينفعش تتكرر زي البريد الإلكتروني - استخدم
includeلما تحتاج تجيب بيانات العلاقات - استخدم
Prisma Studioلمراجعة البيانات بسرعة - خلي بيانات الاتصال بقاعدة البيانات داخل ملف
.env
الخلاصة
Prisma تعتبر واحدة من أفضل الأدوات للتعامل مع قواعد البيانات في مشاريع Node.js، لأنها بتوفر طريقة سهلة وآمنة وسريعة بدل كتابة SQL بشكل يدوي.
من خلال Prisma تقدر تعرف الجداول داخل ملف schema.prisma، وتعمل Migration، وتستخدم Prisma Client لإضافة وتعديل وحذف وجلب البيانات بكل سهولة.
ولو إنت بتبني API باستخدام Express، فـ Prisma هتساعدك جدًا في تنظيم الكود وتقليل الأخطاء وتسريع عملية التطوير.
ببساطة، لو شغال بـ Node.js وعايز تتعامل مع قاعدة البيانات بشكل احترافي، يبقى Prisma اختيار ممتاز جدًا.
مزيد من المقالات : كيفية تقليل حجم مشاريع Flutter على جهازك






