بذر قاعدة البيانات والمصانع
بذر قاعدة البيانات والمصانع
بذر قاعدة البيانات ومصانع النماذج هي أدوات أساسية لملء قاعدة البيانات ببيانات الاختبار. إنها لا تقدر بثمن للتطوير والاختبار والعروض التوضيحية. في هذا الدرس، ستتعلم كيفية إنشاء بيانات وهمية واقعية بكفاءة.
لماذا نستخدم البذور والمصانع؟
تتيح لك البذور والمصانع:
- ملء قاعدة البيانات بسرعة ببيانات الاختبار
- إنشاء بيانات متسقة عبر بيئات التطوير
- إنشاء بيانات واقعية للاختبار والعروض التوضيحية
- إعادة تعيين قاعدة البيانات إلى حالة معروفة
- اختبار تطبيقك بسيناريوهات بيانات مختلفة
مقدمة إلى مصانع النماذج
تستخدم مصانع النماذج مكتبة Faker لإنشاء بيانات وهمية واقعية. يمكن أن يكون لكل نموذج مصنع يحدد حالته الافتراضية.
إنشاء مصنع
# إنشاء مصنع لنموذج
php artisan make:factory ProductFactory
# إنشاء مصنع وتحديد النموذج
php artisan make:factory ProductFactory --model=Product
ينشئ هذا ملف مصنع في database/factories/ProductFactory.php:
<?php
namespace Database\Factories;
use Illuminate\Database\Eloquent\Factories\Factory;
class ProductFactory extends Factory
{
/**
* تعريف الحالة الافتراضية للنموذج.
*/
public function definition(): array
{
return [
'name' => fake()->words(3, true),
'description' => fake()->paragraph(),
'price' => fake()->randomFloat(2, 10, 1000),
'quantity' => fake()->numberBetween(0, 100),
'is_active' => fake()->boolean(80), // احتمال 80٪ من true
'category' => fake()->randomElement(['Electronics', 'Clothing', 'Food', 'Books']),
];
}
}
مكتبة Faker - الطرق الشائعة
توفر Faker مئات الطرق لإنشاء بيانات وهمية واقعية:
// المعلومات الشخصية
fake()->name() // 'John Doe'
fake()->firstName() // 'John'
fake()->lastName() // 'Doe'
fake()->email() // 'john@example.com'
fake()->safeEmail() // رسائل بريد إلكتروني آمنة للاختبار
fake()->phoneNumber() // '+1-555-123-4567'
// العنوان
fake()->address() // عنوان كامل
fake()->city() // 'New York'
fake()->country() // 'United States'
fake()->postcode() // '12345'
fake()->streetAddress() // '123 Main St'
// النص
fake()->word() // كلمة عشوائية واحدة
fake()->words(3) // مصفوفة من 3 كلمات
fake()->words(3, true) // سلسلة من 3 كلمات
fake()->sentence() // جملة عشوائية
fake()->paragraph() // فقرة عشوائية
fake()->text(200) // نص بحد أقصى 200 حرف
// الأرقام
fake()->randomNumber(5) // رقم مكون من 5 أرقام
fake()->numberBetween(1, 100) // رقم بين 1-100
fake()->randomFloat(2, 0, 100) // عائم بمنزلتين عشريتين
// التواريخ
fake()->date() // '2023-05-15'
fake()->dateTime() // كائن DateTime
fake()->dateTimeBetween('-1 year', 'now')
fake()->time() // '14:30:00'
// الإنترنت
fake()->url() // 'https://example.com'
fake()->slug() // 'lorem-ipsum-dolor'
fake()->ipv4() // '192.168.1.1'
fake()->userAgent() // وكيل مستخدم المتصفح
// الملفات والصور
fake()->imageUrl(640, 480) // عنوان URL للصورة
fake()->fileExtension() // 'jpg'
fake()->mimeType() // 'image/jpeg'
// منطقية وعشوائية
fake()->boolean() // true أو false (50/50)
fake()->boolean(70) // احتمال 70٪ من true
fake()->randomElement(['A', 'B', 'C']) // اختر من المصفوفة
fake()->randomElements(['A', 'B', 'C'], 2) // اختر 2
// فريد واختياري
fake()->unique()->email() // بريد إلكتروني فريد
fake()->optional()->email() // بريد إلكتروني أو null
استخدام المصانع
بمجرد تعريف مصنع، يمكنك استخدامه لإنشاء نماذج:
<?php
use App\Models\Product;
// إنشاء منتج واحد
$product = Product::factory()->create();
// إنشاء منتجات متعددة
$products = Product::factory()->count(50)->create();
// إنشاء بدون الحفظ في قاعدة البيانات
$product = Product::factory()->make();
// إنشاء بسمات مخصصة
$product = Product::factory()->create([
'name' => 'منتج مخصص',
'price' => 99.99,
]);
// إنشاء متعدد بسمات مخصصة
$products = Product::factory()->count(10)->create([
'category' => 'Electronics',
]);
حالات المصنع
تتيح لك الحالات تعريف اختلافات في بيانات المصنع الخاص بك:
<?php
namespace Database\Factories;
use Illuminate\Database\Eloquent\Factories\Factory;
class ProductFactory extends Factory
{
public function definition(): array
{
return [
'name' => fake()->words(3, true),
'price' => fake()->randomFloat(2, 10, 1000),
'quantity' => fake()->numberBetween(0, 100),
'is_active' => true,
];
}
/**
* الإشارة إلى أن المنتج غير متوفر في المخزون.
*/
public function outOfStock(): static
{
return $this->state(fn (array $attributes) => [
'quantity' => 0,
]);
}
/**
* الإشارة إلى أن المنتج غير نشط.
*/
public function inactive(): static
{
return $this->state(fn (array $attributes) => [
'is_active' => false,
]);
}
/**
* الإشارة إلى أن المنتج باهظ الثمن.
*/
public function expensive(): static
{
return $this->state(fn (array $attributes) => [
'price' => fake()->randomFloat(2, 500, 5000),
]);
}
}
استخدام حالات المصنع:
// إنشاء منتج غير متوفر في المخزون
$product = Product::factory()->outOfStock()->create();
// إنشاء منتج غير نشط وباهظ الثمن
$product = Product::factory()
->inactive()
->expensive()
->create();
// إنشاء 10 منتجات غير متوفرة في المخزون
$products = Product::factory()
->count(10)
->outOfStock()
->create();
علاقات المصنع
إنشاء نماذج مع علاقات باستخدام المصانع:
<?php
namespace Database\Factories;
use App\Models\User;
use Illuminate\Database\Eloquent\Factories\Factory;
class PostFactory extends Factory
{
public function definition(): array
{
return [
'user_id' => User::factory(), // إنشاء مستخدم تلقائيًا
'title' => fake()->sentence(),
'content' => fake()->paragraphs(3, true),
'published_at' => fake()->dateTimeBetween('-1 month', 'now'),
];
}
/**
* الإشارة إلى أن المنشور غير منشور.
*/
public function unpublished(): static
{
return $this->state(fn (array $attributes) => [
'published_at' => null,
]);
}
}
إنشاء منشورات مع علاقات:
// إنشاء منشور مع مستخدم جديد
$post = Post::factory()->create();
// إنشاء منشور لمستخدم موجود
$user = User::find(1);
$post = Post::factory()->create([
'user_id' => $user->id,
]);
// إنشاء مستخدم مع 5 منشورات
$user = User::factory()
->has(Post::factory()->count(5))
->create();
// بناء جملة بديل
$user = User::factory()
->hasPosts(5)
->create();
// إنشاء منشورات بحالة محددة
$user = User::factory()
->has(Post::factory()->count(3)->unpublished())
->create();
// علاقات متعدد إلى متعدد
$post = Post::factory()
->hasAttached(Tag::factory()->count(3))
->create();
بذور قاعدة البيانات
البذور هي فئات تملأ قاعدة البيانات بالبيانات. الباذر الرئيسي هو DatabaseSeeder.php.
إنشاء باذر
# إنشاء باذر جديد
php artisan make:seeder ProductSeeder
ينشئ هذا ملف باذر في database/seeders/ProductSeeder.php:
<?php
namespace Database\Seeders;
use App\Models\Product;
use Illuminate\Database\Seeder;
class ProductSeeder extends Seeder
{
/**
* تشغيل بذور قاعدة البيانات.
*/
public function run(): void
{
// إنشاء 50 منتجًا باستخدام المصنع
Product::factory()->count(50)->create();
// إنشاء منتجات محددة
Product::create([
'name' => 'منتج مميز',
'description' => 'هذا منتج مميز',
'price' => 149.99,
'quantity' => 100,
'is_active' => true,
]);
// إنشاء منتجات بحالات مختلفة
Product::factory()->count(10)->outOfStock()->create();
Product::factory()->count(5)->expensive()->create();
}
}
DatabaseSeeder
الباذر الرئيسي الذي يستدعي البذور الأخرى:
<?php
namespace Database\Seeders;
use Illuminate\Database\Seeder;
class DatabaseSeeder extends Seeder
{
/**
* بذر قاعدة بيانات التطبيق.
*/
public function run(): void
{
// استدعاء بذور محددة
$this->call([
UserSeeder::class,
CategorySeeder::class,
ProductSeeder::class,
PostSeeder::class,
TagSeeder::class,
]);
// أو إنشاء بيانات مباشرة
\App\Models\User::factory()->count(10)->create();
// إنشاء مستخدم مسؤول
\App\Models\User::factory()->create([
'name' => 'مستخدم مسؤول',
'email' => 'admin@example.com',
'is_admin' => true,
]);
}
}
تشغيل البذور
# تشغيل جميع البذور (DatabaseSeeder)
php artisan db:seed
# تشغيل باذر محدد
php artisan db:seed --class=ProductSeeder
# هجرة جديدة مع البذر
php artisan migrate:fresh --seed
# التحديث مع البذر
php artisan migrate:refresh --seed
migrate:fresh يسقط جميع الجداول ويعيد إنشاءها. لا تستخدم هذا أبدًا في الإنتاج! قم دائمًا بعمل نسخة احتياطية من قاعدة البيانات أولاً.
مثال بذر متقدم
<?php
namespace Database\Seeders;
use App\Models\User;
use App\Models\Post;
use App\Models\Tag;
use App\Models\Comment;
use Illuminate\Database\Seeder;
class BlogSeeder extends Seeder
{
public function run(): void
{
// إنشاء العلامات أولاً
$tags = Tag::factory()->count(10)->create();
// إنشاء 5 مستخدمين، كل منهم لديه 10 منشورات
User::factory()
->count(5)
->has(
Post::factory()
->count(10)
->has(Comment::factory()->count(5)) // 5 تعليقات لكل منشور
)
->create()
->each(function ($user) use ($tags) {
// إرفاق علامات عشوائية لمنشورات كل مستخدم
$user->posts->each(function ($post) use ($tags) {
$post->tags()->attach(
$tags->random(rand(1, 3))->pluck('id')
);
});
});
// إنشاء مستخدم مسؤول مع منشورات خاصة
$admin = User::factory()->create([
'name' => 'مسؤول',
'email' => 'admin@blog.com',
'is_admin' => true,
]);
Post::factory()
->count(5)
->create(['user_id' => $admin->id])
->each(function ($post) use ($tags) {
$post->tags()->attach($tags->random(3));
});
}
}
التسلسلات في المصانع
إنشاء بيانات متسلسلة باستخدام طريقة sequence():
// التبديل بين حالتين
$products = Product::factory()
->count(10)
->sequence(
['is_active' => true],
['is_active' => false],
)
->create();
// زيادة القيم
$products = Product::factory()
->count(5)
->sequence(fn ($sequence) => [
'name' => 'منتج ' . ($sequence->index + 1),
'quantity' => ($sequence->index + 1) * 10,
])
->create();
قم بإنشاء إعداد بذر كامل للتجارة الإلكترونية:
- إنشاء مصانع لـ: Product، Category، Order، OrderItem
- يجب أن تنتمي المنتجات إلى فئات
- يجب أن تحتوي الطلبات على عناصر طلب متعددة
- إنشاء حالات مصنع: featuredProduct، onSale، newArrival
- إنشاء بذور تولد: 10 فئات، 100 منتج، 50 طلب
- تأكد من أن كل طلب يحتوي على 1-5 منتجات عشوائية
قم بإنشاء نظام بذر مدونة مع علاقات كاملة:
- إنشاء 10 مستخدمين (1 مسؤول، 9 عاديين)
- كل مستخدم عادي لديه 5-10 منشورات
- كل منشور لديه 3-10 تعليقات
- إنشاء 20 علامة وإرفاق 2-5 علامات عشوائيًا لكل منشور
- استخدام حالات المصنع لـ: publishedPost، draftPost، featuredPost
- 80٪ من المنشورات يجب أن تكون منشورة، 20٪ مسودات
قم بإنشاء UserFactory ببيانات واقعية:
- إنشاء أسماء ورسائل بريد إلكتروني وأرقام هواتف واقعية
- إضافة عناوين URL للصور الرمزية باستخدام imageUrl من Faker
- إنشاء نص سيرة ذاتية (2-3 جمل)
- إضافة عيد ميلاد (بين 18-70 عامًا)
- إنشاء حالات: verified، unverified، banned
- إنشاء 100 مستخدم بـ 70٪ تم التحقق منهم، 25٪ لم يتم التحقق منهم، 5٪ محظورين
أفضل الممارسات
- استخدم المصانع للمرونة: حدد البيانات الأساسية في المصانع، وخصص في البذور.
- احتفظ بتنظيم البذور: قم بإنشاء بذور منفصلة لنماذج أو ميزات مختلفة.
- استخدم بيانات واقعية: توفر Faker بيانات واقعية تساعد في اكتشاف الأخطاء.
- استفد من الحالات: حدد الاختلافات الشائعة كحالات مصنع لإعادة الاستخدام.
- اختبر العلاقات: قم بزراعة البيانات ذات الصلة لاختبار علاقاتك واستعلاماتك.
- تحكم في إصدار البذور: أرسل البذور لمشاركة بيانات الاختبار المتسقة عبر الفرق.
- هجرات جديدة في التطوير: استخدم
migrate:fresh --seedلإعادة تعيين قاعدة البيانات.
الخلاصة
في هذا الدرس، تعلمت:
- إنشاء مصانع نماذج لإنشاء بيانات وهمية
- استخدام مكتبة Faker لبيانات اختبار واقعية
- تعريف حالات المصنع لاختلافات البيانات
- إنشاء نماذج مع علاقات باستخدام المصانع
- كتابة بذور قاعدة البيانات لملء البيانات
- تشغيل البذور وإدارة بيانات الاختبار
- تقنيات البذر المتقدمة للعلاقات المعقدة
البذور والمصانع هي أدوات أساسية للتطوير والاختبار. أتقنها، وستوفر ساعات لا تحصى في إعداد بيئات الاختبار!