LEVERAGING VIRTUAL GENERATED COLUMNS IN MYSQL USING LARAVEL
Dec 01, 2023 Copy Link
السلام عليكم 🙌
يارب تكونوا جميعاً بخير تعالوا نتكلم النهارده عن موضوع جديد تماماً و مفيش كلام كتير عليه و هو ال Virtual Generated Columns 🔥
في البداية كدا ال Generated Columns هي feature في ال MySQL و ظهرت مع ال v5.7 و ال MySQL قالت إن ال feature دي بتعمل populate لل values في ال columns علي حسب الطريقة اللي إنت محددها, فتعالوا كدا نشوف الموضوع دا بمثال لطيف جداً في لارفيل 😋
تعالوا الأول نعمل create لل Product model بال migration و ال factory عن طريق ال command دا 👇
php artisan make::model Product -mf
بعد كدا هنفتح ال products migration file و هنضيف فيه ال columns دي 🗃
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('products', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->decimal('unit_price', 8, 2);
$table->integer('quantity');
$table->decimal('total_price', 8, 2)
->storedAs('unit_price * quantity');
$table->timestamps();
});
}
و دلوقتي بعد ما ضيفنا ال columns بتاعتنا تعالوا نعمل migrate لل database عن طريق ال command دا 🎯
php artisan migrate
لو جينا نفتح ال structure الخاص بالجدول دا هنلاقي إن ال total_price column فعلاً STORED GENERATED, طيب دا معناه إيه؟ 🤔
زي ما قولت قبل كدا إن ال MySQL بتعمل populate لل values علي حسب ال expression اللي إنت عايزه و علي حسب المثال دا أنا بقول لل MySQL إن قيمة ال total_price column هتتحسب عن طريق ضرب قيمة ال unite_price column في قيمة ال quantity column..تعالوا نجرب الموضوع دا بنفسنا كدا 😃
بس الأول تعالوا نعدل ال ProductFactory و نخليه بالشكل دا 👇
/**
* Define the model's default state.
*
* @return array<string, mixed>
*/
public function definition(): array
{
return [
'name' => $this->faker->name,
'unit_price' => $this->faker->randomNumber(3),
'quantity' => $this->faker->randomDigit(),
];
}
و كمان هنعمل override لل fillable property في ال Product model زي كدا 👇
class Product extends Model
{
use HasFactory;
/**
* The attributes that are mass assignable.
*
* @var array<int, string>
*/
protected $fillable = [
'name',
'unit_price',
'quantity'
];
}
تعالوا بقا نضيف records في الجدول عشان نشوف ال total_price column هيحصل فيه إيه عن طريق ال command دا 🧐
php artisan tinker
ال command دا هيفتحلي Psy Shell و من خلاله أقدر اكتب اي Laravel Code عشان يتنفذ, يلا بينا نضيف ال fake records بإستخدام ال ProductFactory عن طريق ال command دا 👇
\App\Models\Product::factory(5)->create();
لو جينا نفتح ال database هنلاحظ إن ال five records إضافوا تمام و كمان ال total_price column حصله populate عن طريق ال expression اللي أنا حددته في ال migration 🚀
و دلوقتي بعد ما شوفنا ال storedAs ميثود تعالوا نشوف ال virtualAs ميثود 🤗
تعالوا نضيف column جديد بإستخدام ال virtualAs ميثود في ال products table عن طريق ال command دا 🛠
php artisan make:migration adds_v_total_price_column_to_products_table
ال command اللي فات دا هيعمل create لملف migration جديد و من خلاله أقدر أضيف ال column بتاعي بالطريقة اللي جاية دي 🤙
/**
* Run the migrations.
*/
public function up(): void
{
Schema::table('products', function (Blueprint $table) {
$table
->decimal('v_total_price', 8, 2)
->after('total_price')
->virtualAs('unit_price * quantity');
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::table('products', function (Blueprint $table) {
$table->dropColumn('v_total_price');
});
}
لو جينا نعمل migrate بال command اللي إستخدمناه قبل كدا و جينا نفتح ال database هنلاحظ إن ال column دا مش موجود! بس لو فتحنا ال sturcture الخاص بالجدول هنلاحظ إنه موجود بعد ال total_price column 🤯
و دا يرجع لكونه من نوع ال VIRTUAL GENERATED و دا علي عكس ال STORED GENERATED 🤞
محتاجين بقا نضيف كام record جديد عشان نتأكد إن ال expression شغال تمام, و عشان نعمل كدا هنستخدم ال command اللي فات عن طريق ال Psy Shell 💻
هنلاحظ إن فعلاً القيم الموجودة و كله تمام, و حتي لو عملنا تعديل علي قيمة ال unit_price أو ال quantity هنلاقي إن قيمة ال total_price و ال v_total_price إتعدلوا بشكل تلقائي و دي عظمة ال generated columns 🚀
طب نسئل نفسنا سؤال كدا و هو إيه فائدة ال generated columns؟ 🤔
أنا شايف من وجهه نظري إن في فايدتين و هما كالآتي 👀
1-) ال storedAs و ال virtualAs ميثودز ممكن أعملهم chaining لميثود مهمة جداً إسمها index و دي بتساعدنا في إن ال query تكون أسرع في عملية ال retrieving للداتا.
2-) الموضوع دا مخلنيش أكتب ميثود إضافية عشان أحسب من خلالها ال total_price و ال v_total_price في حالة ال creation أو ال update.
وبكدا نكون خلصنا موضوعنا الجميل و أتمني تكون إستفدت ✔