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.

 

وبكدا نكون خلصنا موضوعنا الجميل و أتمني تكون إستفدت ✔

Share via

Mahmoud Ramadan

Mahmoud Ramadan

Mahmoud is the creator of Digging Code and a contributor to Laravel since 2020.

Most recent

  • Get your environment ready to welcome Laravel v12

    Get your environment ready to we...

    FREE

  • How to generate Arabic PDF using TCPDF

    How to generate Arabic PDF using...

    FREE

  • What is SQL Injection

    What is SQL Injection

    FREE