المحولات والتحويل
تسمح لك المحولات والوصولات بتحويل قيم سمات Sutando عند استرجاعها أو تعيينها على مثيلات النموذج.
الوصولات والمحولات
تعريف الوصول
لتعريف الوصول، قم بإنشاء طريقة مسماة بصيغة camelCase attribute{Attribute}
في النموذج لتمثيل السمة القابلة للوصول. يتوافق اسم هذه الطريقة مع تمثيل السمة الحقيقية للنموذج/حقل قاعدة البيانات.
في هذا المثال، سنقوم بتعريف وصول للسمة first_name
. سيتم استدعاء الوصول تلقائيًا بواسطة Sutando عند محاولة استرجاع قيمة السمة first_name
:
import { BaseModel, AttributeModel } from "kawkab";
class User extends Model {
attributeFirstName() {
return AttributeModel.make({
get: value => value.toUpperCase()
})
}
}
تُعيد جميع طرق الوصول مثيل Attribute
الذي يحدد كيفية الوصول إلى السمة وكيفية تغيير السمة. في هذا المثال، نقوم فقط بتعريف كيفية الوصول إلى الخاصية. للقيام بذلك، نقدم المعامل get
إلى منشئ فئة Attribute
.
كما ترى، يتم تمرير القيمة الأصلية للعمود إلى الوصول، مما يسمح لك بالتلاعب بالقيمة وإعادتها. للوصول إلى قيمة الوصول، يمكنك ببساطة الوصول إلى السمة first_name
على مثيل النموذج:
const user = await User.query().find(1);
const firstName = user.first_name;
:::tip إذا كنت ترغب في إضافة هذه القيم المحسوبة إلى تمثيلات الكائن / JSON لنموذجك، ستحتاج إلى إضافتها. :::
في بعض الأحيان قد تحتاج وصولك إلى تحويل سمات نموذج متعددة إلى “كائن قيمة” واحد. للقيام بذلك، يمكن لوصولك قبول معامل ثاني attributes
، الذي سيتم تزويده تلقائيًا إلى الوصول وسيحتوي على كائن يحتوي على جميع سمات النموذج الحالية:
attributeFullName() {
return AttributeModel.make({
get: (value, attributes) => `${attributes.first_name} ${attributes.last_name}`
})
}
تعريف المحول
لتعريف المحول، يمكنك تقديم المعامل set
عند تعريف السمة الخاصة بك. دعونا نعرف محولًا للسمة first_name
. سيتم استدعاء هذا المحول تلقائيًا عندما نحاول تعيين قيمة السمة first_name
على النموذج:
import { BaseModel, AttributeModel } from "kawkab";
class User extends Model {
attributeFirstName() {
return AttributeModel.make({
get: value => value.toUpperCase(),
set: value => value.toLocalLowerCase()
})
}
}
سيستقبل المحول القيمة التي يتم تعيينها على السمة، مما يسمح لك بالتلاعب بالقيمة وتعيين القيمة المعدلة على خاصية attributes
الداخلية لنموذج Sutando. لاستخدام محولنا، نحتاج فقط إلى تعيين السمة first_name
على نموذج Sutando:
const user = User.query().find(1);
user.first_name = 'Sally';
في هذا المثال، سيتم استدعاء رد الاتصال set
بالقيمة Sally
. ثم سيقوم المحول بتطبيق وظيفة toLocalLowerCase
على الاسم وتعيين قيمته الناتجة في attributes
الداخلية للنموذج.
تحويل سمات متعددة
في بعض الأحيان قد يحتاج محولك إلى تعيين سمات متعددة على النموذج الأساسي. للقيام بذلك، يمكنك إرجاع كائن من رد الاتصال set
. يجب أن يتوافق كل مفتاح في الكائن مع سمة أساسية / عمود قاعدة بيانات مرتبط بالنموذج:
attributeFullName() {
return AttributeModel.make({
get: (value, attributes) => `${attributes.first_name} ${attributes.last_name}`,
set: (value) => ({
first_name: value.split(' ')[0],
last_name: value.split(' ')[1],
}),
});
}
تحويل السمات
يوفر تحويل السمات وظيفة مشابهة للوصولات والمحولين دون الحاجة إلى تعريف أي طرق إضافية على النموذج الخاص بك. بدلاً من ذلك، توفر خاصية casts
للنموذج طريقة مريحة لتحويل السمات إلى أنواع بيانات شائعة.
يجب أن تكون خاصية casts
كائنًا حيث يكون المفتاح هو اسم السمة التي يتم تحويلها والقيمة هي النوع الذي ترغب في تحويل العمود إليه. الأنواع المدعومة للتحويل هي:
integer
int
float
double
string
boolean
bool
collection
date
datetime
json
object
لإظهار تحويل السمات، دعونا نحول السمة is_admin
، التي يتم تخزينها في قاعدة البيانات كعدد صحيح (0
أو 1
) إلى قيمة منطقية:
import { BaseModel } from "kawkab";
class User extends Model {
// السمات التي يجب تحويلها.
casts = {
is_admin: 'boolean',
};
}
بعد تعريف التحويل، سيتم دائمًا تحويل السمة is_admin
إلى منطقية عند الوصول إليها، حتى إذا تم تخزين القيمة الأساسية في قاعدة البيانات كعدد صحيح:
const user = await User.query().find(1);
if (user.is_admin) {
// ...
}
:::tip يجب ألا تعرف أبدًا تحويلًا (أو سمة) تحمل نفس اسم العلاقة أو تعيين تحويل للمفتاح الأساسي للنموذج. :::
تحويل JSON
يعتبر تحويل json مفيدًا بشكل خاص عند العمل مع الأعمدة التي يتم تخزينها كسلسلة JSON
. على سبيل المثال، إذا كانت قاعدة البيانات الخاصة بك تحتوي على نوع حقل JSON
أو TEXT
يحتوي على JSON مسلسل، فإن إضافة تحويل json إلى تلك السمة سيقوم تلقائيًا بإلغاء تسلسل السمة عند الوصول إليها على النموذج الخاص بك:
import { BaseModel } from "kawkab";
class User extends Model {
// السمات التي يجب تحويلها.
casts = {
options: 'json',
};
}
بمجرد تعريف التحويل، يمكنك الوصول إلى السمة options
وسيتم تلقائيًا إلغاء تسلسلها من JSON
إلى كائن. عند تعيين قيمة السمة options
، سيتم تلقائيًا تسلسل الكائن المعطى مرة أخرى إلى JSON للتخزين:
import { BaseModel } from "kawkab";
const user = await User.query().find(1);
const options = user.options;
options.key = value;
user.options = options;
await user.save();
:::tip لا يمكن لتعديل السمات نفسها مباشرةً تحديث بيانات النموذج، لذلك فإن الاستخدام التالي غير صحيح:
const user = await User.query().find(1);
user.options.key = value;
:::
تحويل التاريخ
بشكل افتراضي، سيقوم Sutando بتحويل أعمدة created_at
و updated_at
إلى مثيلات Date
. يمكنك تحويل سمات تاريخ إضافية عن طريق تعريف تحويلات تاريخ إضافية داخل خاصية casts
الخاصة بالنموذج الخاص بك. عادةً ما يجب تحويل التواريخ باستخدام أنواع تحويل datetime
.
عند تعريف تحويل date
أو datetime
، يمكنك أيضًا تحديد تنسيق التاريخ. سيتم استخدام هذا التنسيق عند تسلسل النموذج إلى كائن أو JSON:
casts = {
created_at: 'datetime:YYYY-MM-DD',
};
يمكنك تخصيص تنسيق التسلسل الافتراضي لجميع تواريخ النموذج الخاص بك عن طريق تعريف طريقة serializeDate
على النموذج الخاص بك. لا تؤثر هذه الطريقة على كيفية تنسيق تواريخك للتخزين في قاعدة البيانات:
const dayjs = require('dayjs');
class User extends Model {
serializeDate(date) {
return dayjs(date).format('YYYY-MM-DD');
}
}
لتحديد التنسيق الذي يجب استخدامه عند تخزين تواريخ النموذج فعليًا داخل قاعدة البيانات الخاصة بك، يجب عليك تعريف خاصية dateFormat
على النموذج الخاص بك:
class User extends Model {
dateFormat = 'X'
}
قائمة بجميع التنسيقات المتاحة
التنسيق | الناتج | الوصف |
---|---|---|
YY | 18 | السنة برقمين |
YYYY | 2018 | السنة بأربعة أرقام |
M | 1-12 | الشهر، يبدأ من 1 |
MM | 01-12 | الشهر، برقمين |
MMM | Jan-Dec | اسم الشهر المختصر |
MMMM | January-December | اسم الشهر الكامل |
D | 1-31 | يوم الشهر |
DD | 01-31 | يوم الشهر، برقمين |
d | 0-6 | يوم الأسبوع، الأحد كـ 0 |
dd | Su-Sa | اسم اليوم المختصر |
ddd | Sun-Sat | اسم اليوم القصير |
dddd | Sunday-Saturday | اسم اليوم الكامل |
H | 0-23 | الساعة |
HH | 00-23 | الساعة، برقمين |
h | 1-12 | الساعة، 12 ساعة |
hh | 01-12 | الساعة، 12 ساعة، برقمين |
m | 0-59 | الدقيقة |
mm | 00-59 | الدقيقة، برقمين |
s | 0-59 | الثانية |
ss | 00-59 | الثانية، برقمين |
SSS | 000-999 | المللي ثانية، برقمين |
Z | +05:00 | الفرق عن توقيت جرينتش، ±HH:mm |
ZZ | +0500 | الفرق عن توقيت جرينتش، ±HHmm |
A | AM PM | |
a | am pm | |
Q | 1-4 | الربع |
Do | 1st 2nd … 31st | يوم الشهر مع الترتيب |
k | 1-24 | الساعة، يبدأ من 1 |
kk | 01-24 | الساعة، برقمين، يبدأ من 1 |
X | 1360013296 | الطابع الزمني Unix بالثواني |
x | 1360013296123 | الطابع الزمني Unix بالمللي ثانية |
تحويل التاريخ، التسلسل، والمناطق الزمنية
بشكل افتراضي، ستقوم تحويلات date
و datetime
بتسلسل التواريخ إلى سلسلة تاريخ ISO-8601 UTC (2012-12-12T12:25:36.000000Z)، بغض النظر عن المنطقة الزمنية المحددة في خيار تكوين المنطقة الزمنية لتطبيقك.
إذا تم تطبيق تنسيق مخصص على تحويل date
أو datetime
، مثل datetime:YYYYY-MM-DD HH:mm:ss
، سيتم استخدام المنطقة الزمنية UTC أثناء تسلسل التاريخ.
التحويلات المخصصة
لدى Sutando مجموعة متنوعة من أنواع التحويل المدمجة والمفيدة؛ ومع ذلك، قد تحتاج أحيانًا إلى تعريف أنواع التحويل الخاصة بك. جميع فئات التحويل المخصصة تمتد CastsAttributes
. يجب على الفئات التي تنفذ هذه الواجهة تعريف طريقة get
و set
. تكون طريقة get
مسؤولة عن تحويل قيمة خام من قاعدة البيانات إلى قيمة تحويل، بينما يجب أن تحول طريقة set
قيمة التحويل إلى قيمة خام يمكن تخزينها في قاعدة البيانات. كمثال، سنعيد تنفيذ نوع التحويل المدمج json
كنوع تحويل مخصص:
// casts/json.js
const { Model, CastsAttributes } from "kawkab";
class Json extends CastsModel {
// تحويل القيمة المعطاة.
static get(model, key, value, attributes) {
try {
return JSON.parse(value);
} catch (e) {
return null;
}
}
// تحضير القيمة المعطاة للتخزين.
static set(model, key, value, attributes) {
return JSON.stringify(value);
}
}
بمجرد تعريف نوع تحويل مخصص، يمكنك إرفاقه بسمة نموذج باستخدام فئته:
const Json = require('./casts/json');
class User extends Model {
// السمات التي يجب تحويلها.
casts = {
options: Json,
};
}