پرش به مطلب اصلی

ایجاد کلاس مدل جدید

این راهنما نحوه ایجاد یک کلاس مدل جدید در فریمورک کیمیا را توضیح می‌دهد.

پیش‌نیازها

قبل از شروع، اطمینان حاصل کنید که:

  • یک اپلیکیشن کیمیا دارید (به راهنمای ایجاد اپلیکیشن جدید مراجعه کنید)
  • با ساختار پایه مدل‌ها و Sequelize آشنا هستید
  • رابط TypeScript مدل را تعریف کرده‌اید

ساختار کلاس مدل

کلاس پایه (Base Class)

هر کلاس مدل باید از کلاس Model کتابخانه Sequelize ارث‌بری کند:

import { Model } from 'sequelize';
import { MyModelInterface } from '../interfaces';

export class MyModel extends Model<MyModelInterface> { }

تابع load

هر مدل باید دارای یک تابع load باشد که مدل را مقداردهی اولیه می‌کند:

import { DataTypes, Model } from 'sequelize';
import { Global } from '@core/global';
import { MyModelInterface } from '../interfaces';

export class MyModel extends Model<MyModelInterface> { }

export function load() {
return MyModel.init({
// ویژگی‌های مدل اینجا تعریف می‌شوند
id: {
type: DataTypes.BIGINT,
autoIncrement: true,
primaryKey: true,
},
name: {
type: DataTypes.STRING,
allowNull: false,
},
// سایر فیلدها...
}, {
sequelize: Global.Database.dbConn,
modelName: 'MyModel',
tableName: 'my_models',
createdAt: 'created_at',
updatedAt: 'updated_at',
deletedAt: 'deleted_at',
paranoid: true, // برای soft delete
});
}

تعریف ویژگی‌های مدل

انواع داده‌ها

از انواع داده‌های Sequelize استفاده کنید:

import { DataTypes } from 'sequelize';

// انواع پایه
DataTypes.STRING // رشته متنی
DataTypes.TEXT // متن طولانی
DataTypes.INTEGER // عدد صحیح
DataTypes.BIGINT // عدد صحیح بزرگ
DataTypes.FLOAT // عدد اعشاری
DataTypes.DOUBLE // عدد اعشاری دوگانه
DataTypes.DECIMAL // عدد اعشاری دقیق
DataTypes.BOOLEAN // بولین
DataTypes.DATE // تاریخ
DataTypes.DATE(6) // تاریخ با میکروثانیه
DataTypes.JSON // داده JSON
DataTypes.UUID // UUID

گزینه‌های فیلد

هر فیلد می‌تواند گزینه‌های مختلفی داشته باشد:

{
type: DataTypes.STRING, // نوع داده
allowNull: false, // اجباری بودن
defaultValue: 'default', // مقدار پیش‌فرض
unique: true, // یکتا بودن
primaryKey: true, // کلید اصلی
autoIncrement: true, // افزایش خودکار
comment: 'توضیح فیلد', // کامنت
}

گزینه‌های مدل

گزینه‌های پایه

{
sequelize: Global.Database.dbConn, // اتصال دیتابیس
modelName: 'MyModel', // نام مدل
tableName: 'my_models', // نام جدول
timestamps: true, // فعال بودن timestamps
createdAt: 'created_at', // نام فیلد created_at
updatedAt: 'updated_at', // نام فیلد updated_at
deletedAt: 'deleted_at', // نام فیلد deleted_at
paranoid: true, // فعال بودن soft delete
}

گزینه‌های پیشرفته

{
// ایندکس‌ها
indexes: [
{
unique: true,
fields: ['email', 'username']
}
],

// هوک‌ها (Hooks)
hooks: {
beforeCreate: (instance) => {
// کد قبل از ایجاد
},
afterUpdate: (instance) => {
// کد بعد از بروزرسانی
}
},

// اسکوپ‌ها (Scopes)
scopes: {
active: {
where: { status: 'active' }
}
}
}

تعریف رابط TypeScript

رابط مدل بهتر است در فایل app/interfaces/models/ تعریف شود:

// app/interfaces/models/MyModel.ts
export interface MyModelInterface {
id?: number;
name: string;
description?: string;
status?: 'active' | 'inactive';
created_at?: number;
updated_at?: number;
deleted_at?: number;
}

ثبت مدل

مدل‌های اپلیکیشن

مدل‌های اپلیکیشن در فایل app/models/models.ts ثبت می‌شوند:

import { ModelDefinition } from "@core/server/interfaces";
import { MyModel } from './MyModel';
export type AppModelName =
| "MyModel";
export const AppModels: ModelDefinition<AppModelName>[] = [
{ name: "MyModel", class: MyModel },
];

مدل‌های هسته

مدل‌های هسته در فایل core/database/models/index.ts ثبت می‌شوند و در تنظیمات INIT_MODELS اضافه می‌شوند.

مثال کامل

1. تعریف رابط

// app/interfaces/models/Product.ts
export interface ProductModel {
id?: number;
name: string;
description?: string;
price: number;
category_id?: number;
status: 'active' | 'inactive';
created_at?: number;
updated_at?: number;
deleted_at?: number;
}

2. ایجاد کلاس مدل

// app/models/Product.ts
import { Model, DataTypes } from 'sequelize';
import { Global } from '@core/global';
import { ProductModel } from '../interfaces/models/Product';

export class Product extends Model<ProductModel> { }

export function load() {
return Product.init({
id: {
type: DataTypes.BIGINT,
autoIncrement: true,
primaryKey: true,
},
name: {
type: DataTypes.STRING(255),
allowNull: false,
comment: 'نام محصول',
},
description: {
type: DataTypes.TEXT,
allowNull: true,
comment: 'توضیح محصول',
},
price: {
type: DataTypes.DECIMAL(10, 2),
allowNull: false,
defaultValue: 0,
comment: 'قیمت محصول',
},
category_id: {
type: DataTypes.BIGINT,
allowNull: true,
comment: 'شناسه دسته‌بندی',
},
status: {
type: DataTypes.ENUM('active', 'inactive'),
allowNull: false,
defaultValue: 'active',
comment: 'وضعیت محصول',
},
created_at: DataTypes.DATE(6),
updated_at: DataTypes.DATE(6),
deleted_at: DataTypes.DATE(6),
}, {
sequelize: Global.Database.dbConn,
modelName: 'Product',
tableName: 'products',
createdAt: 'created_at',
updatedAt: 'updated_at',
deletedAt: 'deleted_at',
paranoid: true,
indexes: [
{
fields: ['category_id'],
},
{
fields: ['status'],
},
],
});
}

3. ثبت مدل

import { ModelDefinition } from "@core/server/interfaces";
import { Product } from './Product';
export type AppModelName =
| "Product";
export const AppModels: ModelDefinition<AppModelName>[] = [
{ name: "Product", class: Product },
];

استفاده از مدل

عملیات پایه

import { Product } from './Product';
// ایجاد رکورد جدید
const product = await Product.create({
name: 'محصول نمونه',
price: 100000,
status: 'active',
});

// جستجو
const products = await Product.findAll({
where: { status: 'active' },
limit: 10,
});

// جستجو با ID
const product = await Product.findByPk(1);

// بروزرسانی
await product.update({ price: 150000 });

// حذف (soft delete اگر paranoid فعال باشد)
await product.destroy();

عملیات پیشرفته

// جستجو با شرایط پیچیده
const products = await Product.findAll({
where: {
price: { [Op.gte]: 50000 },
status: 'active',
},
include: [
{ model: Category, as: 'category' }
],
order: [['created_at', 'DESC']],
limit: 20,
offset: 0,
});

// شمارش رکوردها
const count = await Product.count({
where: { status: 'active' }
});

// بروزرسانی گروهی
await Product.update(
{ status: 'inactive' },
{ where: { category_id: 5 } }
);

نکات مهم

  • نام جدول بهتر است جمع و با حروف کوچک باشد
  • بهتر است از DataTypes.DATE(6) برای فیلدهای تاریخ استفاده کنید
  • از paranoid: true برای soft delete استفاده کنید
  • فیلدهای اجباری را با allowNull: false تعریف کنید
  • از کامنت‌ها برای توضیح فیلدها استفاده کنید
  • ایندکس‌ها را برای فیلدهای جستجو شده تعریف کنید

توسعه بیشتر

پس از ایجاد کلاس مدل پایه، می‌توانید:

  • هوک‌ها و اسکوپ‌های سفارشی اضافه کنید
  • متدهای استاتیک و نمونه برای عملیات خاص پیاده‌سازی کنید