نسخه:

الکوئنت: کارخانه ها

معرفی

هنگام آزمایش برنامه یا نمایش پایگاه داده خود، ممکن است لازم باشد چند رکورد را در پایگاه داده خود وارد کنید. به جای تعیین دستی مقدار هر ستون، لاراول به شما امکان می دهد مجموعه ای از ویژگی های پیش فرض را برای هر یک از مدل های Eloquent خود با استفاده از کارخانه های مدل تعریف کنید.

برای مشاهده نمونه ای از نحوه نوشتن یک کارخانه، به database/factories/UserFactory.php فایل موجود در برنامه خود نگاهی بیندازید. این کارخانه با تمام برنامه های جدید لاراول گنجانده شده است و شامل تعریف کارخانه زیر است:

namespace Database\Factories;
 
use Illuminate\Database\Eloquent\Factories\Factory;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Str;
 
/**
* @extends \Illuminate\Database\Eloquent\Factories\Factory<\App\Models\User>
*/
class UserFactory extends Factory
{
/**
* The current password being used by the factory.
*/
protected static ?string $password;
 
/**
* Define the model's default state.
*
* @return array<string, mixed>
*/
public function definition(): array
{
return [
'name' => fake()->name(),
'email' => fake()->unique()->safeEmail(),
'email_verified_at' => now(),
'password' => static::$password ??= Hash::make('password'),
'remember_token' => Str::random(10),
];
}
 
/**
* Indicate that the model's email address should be unverified.
*/
public function unverified(): static
{
return $this->state(fn (array $attributes) => [
'email_verified_at' => null,
]);
}
}

همانطور که می بینید، کارخانه ها در ابتدایی ترین شکل خود، کلاس هایی هستند که کلاس کارخانه پایه لاراول را گسترش می دهند و یک definition متد را تعریف می کنند. این definition متد مجموعه پیش‌فرض مقادیر مشخصه‌ای را که باید هنگام ایجاد یک مدل با استفاده از کارخانه اعمال شوند، برمی‌گرداند.

از طریق Helper، کارخانه ها به کتابخانه Faker fake PHP دسترسی دارند ، که به شما امکان می دهد انواع مختلفی از داده های تصادفی را برای آزمایش و بذر به راحتی تولید کنید.

faker_locale می‌توانید با به‌روزرسانی گزینه موجود در فایل پیکربندی ، منطقه Faker برنامه خود را تغییر دهید config/app.php .

تعریف کارخانه های مدل

کارخانه های تولید کننده

برای ایجاد یک کارخانه، make:factory دستور Artisan را اجرا کنید :

php artisan make:factory PostFactory

کلاس کارخانه جدید در database/factories دایرکتوری شما قرار می گیرد.

کنوانسیون های کشف مدل و کارخانه

هنگامی که کارخانه‌های خود را تعریف کردید، می‌توانید از factory روش استاتیکی که توسط این ویژگی برای مدل‌های خود ارائه می‌شود، استفاده کنید Illuminate\Database\Eloquent\Factories\HasFactory تا نمونه‌ای کارخانه‌ای برای آن مدل ایجاد کنید.

روش این HasFactory صفت factory از قراردادها برای تعیین کارخانه مناسب برای مدلی که صفت به آن اختصاص داده شده است استفاده می کند. به طور خاص، متد به دنبال کارخانه ای در Database\Factories فضای نام می گردد که نام کلاسی مطابق با نام مدل داشته باشد و پسوند آن باشد Factory . اگر این قراردادها برای برنامه یا کارخانه خاص شما اعمال نمی شود، می توانید newFactory روش را روی مدل خود بازنویسی کنید تا نمونه ای از کارخانه مربوطه مدل را مستقیماً بازگردانید:

use Illuminate\Database\Eloquent\Factories\Factory;
use Database\Factories\Administration\FlightFactory;
 
/**
* Create a new factory instance for the model.
*/
protected static function newFactory(): Factory
{
return FlightFactory::new();
}

سپس، یک model ویژگی در کارخانه مربوطه تعریف کنید:

use App\Administration\Flight;
use Illuminate\Database\Eloquent\Factories\Factory;
 
class FlightFactory extends Factory
{
/**
* The name of the factory's corresponding model.
*
* @var class-string<\Illuminate\Database\Eloquent\Model>
*/
protected $model = Flight::class;
}

ایالات کارخانه

روش‌های دستکاری حالت به شما امکان می‌دهد تا تغییرات گسسته‌ای را تعریف کنید که می‌توانند در هر ترکیبی در کارخانه‌های مدل شما اعمال شوند. به عنوان مثال، Database\Factories\UserFactory کارخانه شما ممکن است حاوی یک suspended روش حالت باشد که یکی از مقادیر مشخصه پیش‌فرض آن را تغییر می‌دهد.

روش های تبدیل حالت معمولاً state روش ارائه شده توسط کلاس کارخانه پایه لاراول را می نامند. این state روش یک بسته را می پذیرد که آرایه ای از ویژگی های خام تعریف شده برای کارخانه را دریافت می کند و باید آرایه ای از ویژگی ها را برای اصلاح برگرداند:

use Illuminate\Database\Eloquent\Factories\Factory;
 
/**
* Indicate that the user is suspended.
*/
public function suspended(): Factory
{
return $this->state(function (array $attributes) {
return [
'account_status' => 'suspended',
];
});
}

ایالت "سطل زباله".

اگر می‌توان مدل Eloquent شما را به نرمی حذف کرد ، می‌توانید از روش حالت داخلی استفاده کنید trashed تا نشان دهید که مدل ایجاد شده باید قبلاً "نرم حذف شده" باشد. نیازی نیست که trashed حالت را به صورت دستی تعریف کنید زیرا به طور خودکار در همه کارخانه ها در دسترس است:

use App\Models\User;
 
$user = User::factory()->trashed()->create();

تماس های کارخانه ای

afterMaking تماس‌های کارخانه با استفاده از روش‌های و ثبت می‌شوند afterCreating و به شما اجازه می‌دهند تا پس از ساخت یا ایجاد یک مدل، کارهای بیشتری را انجام دهید. شما باید این کال بک ها را با تعریف configure متدی در کلاس کارخانه خود ثبت کنید. این متد به طور خودکار توسط لاراول زمانی که کارخانه نمونه سازی می شود فراخوانی می شود:

namespace Database\Factories;
 
use App\Models\User;
use Illuminate\Database\Eloquent\Factories\Factory;
 
class UserFactory extends Factory
{
/**
* Configure the model factory.
*/
public function configure(): static
{
return $this->afterMaking(function (User $user) {
// ...
})->afterCreating(function (User $user) {
// ...
});
}
 
// ...
}

همچنین می‌توانید تماس‌های کارخانه‌ای را در روش‌های حالت ثبت کنید تا وظایف دیگری را که مختص یک وضعیت خاص هستند، انجام دهید:

use App\Models\User;
use Illuminate\Database\Eloquent\Factories\Factory;
 
/**
* Indicate that the user is suspended.
*/
public function suspended(): Factory
{
return $this->state(function (array $attributes) {
return [
'account_status' => 'suspended',
];
})->afterMaking(function (User $user) {
// ...
})->afterCreating(function (User $user) {
// ...
});
}

ایجاد مدل ها با استفاده از کارخانه ها

نمونه سازی مدل ها

هنگامی که کارخانه‌های خود را تعریف کردید، می‌توانید از factory روش استاتیکی که توسط این ویژگی برای مدل‌های خود ارائه می‌شود، استفاده کنید Illuminate\Database\Eloquent\Factories\HasFactory تا نمونه‌ای کارخانه‌ای برای آن مدل ایجاد کنید. بیایید به چند نمونه از ایجاد مدل نگاهی بیندازیم. ابتدا از make روشی برای ایجاد مدل‌ها بدون ماندگاری در پایگاه داده استفاده می‌کنیم :

use App\Models\User;
 
$user = User::factory()->make();

می توانید با استفاده از count روش زیر مجموعه ای از مدل های زیادی ایجاد کنید:

$users = User::factory()->count(3)->make();

کشورهای متقاضی

همچنین می توانید هر یک از حالت های خود را در مدل ها اعمال کنید. اگر می خواهید چندین تبدیل حالت را در مدل ها اعمال کنید، می توانید به سادگی روش های تبدیل حالت را مستقیماً فراخوانی کنید:

$users = User::factory()->count(5)->suspended()->make();

ویژگی های برتر

اگر می‌خواهید برخی از مقادیر پیش‌فرض مدل‌های خود را لغو کنید، می‌توانید آرایه‌ای از مقادیر را به make متد ارسال کنید. فقط ویژگی‌های مشخص شده جایگزین می‌شوند در حالی که بقیه ویژگی‌ها روی مقادیر پیش‌فرض خود که توسط کارخانه مشخص شده است، تنظیم می‌شوند:

$user = User::factory()->make([
'name' => 'Abigail Otwell',
]);

روش دیگر، state ممکن است به طور مستقیم در نمونه کارخانه برای انجام یک تبدیل حالت درون خطی فراخوانی شود:

$user = User::factory()->state([
'name' => 'Abigail Otwell',
])->make();

مدل های ماندگار

این create روش نمونه‌های مدل را نمونه‌سازی می‌کند و آنها را با استفاده از روش Eloquent در پایگاه داده نگهداری می‌کند save :

use App\Models\User;
 
// Create a single App\Models\User instance...
$user = User::factory()->create();
 
// Create three App\Models\User instances...
$users = User::factory()->count(3)->create();

می‌توانید ویژگی‌های مدل پیش‌فرض کارخانه را با ارسال آرایه‌ای از ویژگی‌ها به create متد لغو کنید:

$user = User::factory()->create([
'name' => 'Abigail',
]);

دنباله ها

گاهی اوقات ممکن است بخواهید مقدار یک ویژگی مدل معین را برای هر مدل ایجاد شده جایگزین کنید. شما می توانید این کار را با تعریف تبدیل حالت به عنوان یک دنباله انجام دهید. به عنوان مثال، ممکن است بخواهید مقدار یک admin ستون را بین Y و N برای هر کاربر ایجاد شده جایگزین کنید:

use App\Models\User;
use Illuminate\Database\Eloquent\Factories\Sequence;
 
$users = User::factory()
->count(10)
->state(new Sequence(
['admin' => 'Y'],
['admin' => 'N'],
))
->create();

در این مثال، پنج کاربر با admin مقدار Y و پنج کاربر با admin مقدار ایجاد خواهند شد N .

در صورت لزوم، می توانید یک بسته را به عنوان مقدار توالی اضافه کنید. هر بار که دنباله به یک مقدار جدید نیاز دارد، بسته شدن فراخوانی می شود:

use Illuminate\Database\Eloquent\Factories\Sequence;
 
$users = User::factory()
->count(10)
->state(new Sequence(
fn (Sequence $sequence) => ['role' => UserRoles::all()->random()],
))
->create();

در بسته شدن توالی، می‌توانید به $index یا $count ویژگی‌های نمونه دنباله‌ای که به بسته تزریق می‌شود دسترسی داشته باشید. این $index ویژگی شامل تعداد تکرارها از طریق دنباله ای است که تاکنون رخ داده است، در حالی که $count ویژگی شامل تعداد کل دفعاتی است که دنباله فراخوانی می شود:

$users = User::factory()
->count(10)
->sequence(fn (Sequence $sequence) => ['name' => 'Name '.$sequence->index])
->create();

sequence برای راحتی، توالی‌ها ممکن است با استفاده از روشی که به سادگی روش را به صورت داخلی فراخوانی می‌کند، اعمال شوند state . این sequence روش بسته شدن یا آرایه هایی از ویژگی های متوالی را می پذیرد:

$users = User::factory()
->count(2)
->sequence(
['name' => 'First User'],
['name' => 'Second User'],
)
->create();

روابط کارخانه

روابط زیادی دارد

سپس، بیایید ایجاد روابط مدل Eloquent را با استفاده از روش‌های کارخانه روان لاراول بررسی کنیم. ابتدا فرض کنید برنامه ما دارای یک App\Models\User مدل و یک App\Models\Post مدل است. همچنین، فرض کنیم که User مدل hasMany رابطه ای را با Post . ما می توانیم با استفاده از has روش ارائه شده توسط کارخانه های لاراول، کاربری ایجاد کنیم که دارای سه پست باشد . این has روش یک نمونه کارخانه را می پذیرد:

use App\Models\Post;
use App\Models\User;
 
$user = User::factory()
->has(Post::factory()->count(3))
->create();

طبق قرارداد، هنگام انتقال یک Post مدل به has روش، لاراول فرض می‌کند که User مدل باید posts متدی داشته باشد که رابطه را تعریف کند. در صورت لزوم، می توانید به صراحت نام رابطه ای را که می خواهید دستکاری کنید، مشخص کنید:

$user = User::factory()
->has(Post::factory()->count(3), 'posts')
->create();

البته، ممکن است دستکاری های حالت را روی مدل های مرتبط انجام دهید. علاوه بر این، اگر تغییر حالت شما نیاز به دسترسی به مدل والد داشته باشد، می‌توانید یک تبدیل حالت مبتنی بر بسته شدن را تصویب کنید:

$user = User::factory()
->has(
Post::factory()
->count(3)
->state(function (array $attributes, User $user) {
return ['user_type' => $user->type];
})
)
->create();

استفاده از روش های جادویی

برای راحتی، می توانید از روش های رابطه کارخانه جادویی لاراول برای ایجاد روابط استفاده کنید. به عنوان مثال، مثال زیر از قرارداد استفاده می کند تا مشخص کند که مدل های مرتبط باید از طریق یک posts روش رابطه در User مدل ایجاد شوند:

$user = User::factory()
->hasPosts(3)
->create();

هنگام استفاده از روش‌های جادویی برای ایجاد روابط کارخانه، می‌توانید آرایه‌ای از ویژگی‌ها را برای نادیده گرفتن مدل‌های مرتبط ارسال کنید:

$user = User::factory()
->hasPosts(3, [
'published' => false,
])
->create();

اگر تغییر حالت شما نیاز به دسترسی به مدل والد داشته باشد، می‌توانید یک تبدیل حالت مبتنی بر بسته شدن ارائه دهید:

$user = User::factory()
->hasPosts(3, function (array $attributes, User $user) {
return ['user_type' => $user->type];
})
->create();

متعلق به روابط است

اکنون که نحوه ایجاد روابط "بسیار" با استفاده از کارخانه ها را بررسی کردیم، اجازه دهید معکوس این رابطه را بررسی کنیم. این for روش ممکن است برای تعریف مدل مادری که مدل‌های ایجاد شده کارخانه به آن تعلق دارند، استفاده شود. به عنوان مثال، ما می توانیم سه App\Models\Post نمونه مدل ایجاد کنیم که متعلق به یک کاربر است:

use App\Models\Post;
use App\Models\User;
 
$posts = Post::factory()
->count(3)
->for(User::factory()->state([
'name' => 'Jessica Archer',
]))
->create();

اگر قبلاً یک نمونه مدل والد دارید که باید با مدل‌هایی که ایجاد می‌کنید مرتبط باشد، می‌توانید نمونه مدل را به متد ارسال کنید for :

$user = User::factory()->create();
 
$posts = Post::factory()
->count(3)
->for($user)
->create();

استفاده از روش های جادویی

برای راحتی، می‌توانید از روش‌های رابطه کارخانه جادویی لاراول برای تعریف روابط «متعلق به» استفاده کنید. به عنوان مثال، مثال زیر از قرارداد استفاده می کند تا تعیین کند که سه پست باید به user رابطه روی Post مدل تعلق داشته باشند:

$posts = Post::factory()
->count(3)
->forUser([
'name' => 'Jessica Archer',
])
->create();

روابط بسیار به بسیاری

مانند بسیاری از روابط ، روابط "بسیاری از بسیاری" ممکن است با استفاده از has روش ایجاد شوند:

use App\Models\Role;
use App\Models\User;
 
$user = User::factory()
->has(Role::factory()->count(3))
->create();

ویژگی های جدول محوری

اگر نیاز به تعریف ویژگی هایی دارید که باید در جدول محوری / میانی که مدل ها را به هم پیوند می دهد تنظیم شود، می توانید از hasAttached روش استفاده کنید. این متد آرایه ای از نام ها و مقادیر ویژگی های جدول محوری را به عنوان آرگومان دوم خود می پذیرد:

use App\Models\Role;
use App\Models\User;
 
$user = User::factory()
->hasAttached(
Role::factory()->count(3),
['active' => true]
)
->create();

اگر تغییر حالت شما نیاز به دسترسی به مدل مرتبط داشته باشد، می‌توانید یک تبدیل حالت مبتنی بر بسته شدن ارائه دهید:

$user = User::factory()
->hasAttached(
Role::factory()
->count(3)
->state(function (array $attributes, User $user) {
return ['name' => $user->name.' Role'];
}),
['active' => true]
)
->create();

اگر قبلاً نمونه‌های مدلی دارید که می‌خواهید به مدل‌هایی که ایجاد می‌کنید متصل شوند، می‌توانید نمونه‌های مدل را به متد ارسال کنید hasAttached . در این مثال، همان سه نقش به هر سه کاربر پیوست می‌شود:

$roles = Role::factory()->count(3)->create();
 
$user = User::factory()
->count(3)
->hasAttached($roles, ['active' => true])
->create();

استفاده از روش های جادویی

برای راحتی، می‌توانید از روش‌های رابطه کارخانه جادویی لاراول برای تعریف بسیاری از روابط استفاده کنید. به عنوان مثال، مثال زیر از قرارداد استفاده می کند تا مشخص کند که مدل های مرتبط باید از طریق یک roles روش رابطه در User مدل ایجاد شوند:

$user = User::factory()
->hasRoles(1, [
'name' => 'Editor'
])
->create();

روابط چند شکلی

روابط چند شکلی نیز ممکن است با استفاده از کارخانه ها ایجاد شود. روابط چند شکلی "morph many" به همان روشی ایجاد می شوند که روابط معمولی "دارای بسیاری" هستند. به عنوان مثال، اگر یک App\Models\Post مدل morphMany با یک App\Models\Comment مدل رابطه داشته باشد:

use App\Models\Post;
 
$post = Post::factory()->hasComments(3)->create();

شکل به روابط

نمی توان از روش های جادویی برای ایجاد morphTo روابط استفاده کرد. در عوض، for روش باید به طور مستقیم استفاده شود و نام رابطه باید به صراحت ارائه شود. به عنوان مثال، تصور کنید که Comment مدل دارای commentable روشی است که یک morphTo رابطه را تعریف می کند. در این شرایط، می‌توانیم با استفاده از for روش مستقیم، سه نظر ایجاد کنیم که متعلق به یک پست است :

$comments = Comment::factory()->count(3)->for(
Post::factory(), 'commentable'
)->create();

چند شکلی از بسیاری تا بسیاری از روابط

روابط چند شکلی «بسیاری به بسیاری» ( morphToMany / morphedByMany ) ممکن است درست مانند روابط غیرچند شکلی «بسیاری از بسیاری» ایجاد شوند:

use App\Models\Tag;
use App\Models\Video;
 
$videos = Video::factory()
->hasAttached(
Tag::factory()->count(3),
['public' => true]
)
->create();

البته، has روش جادویی نیز ممکن است برای ایجاد روابط چند شکلی "بسیاری به بسیاری" استفاده شود:

$videos = Video::factory()
->hasTags(3, ['public' => true])
->create();

تعریف روابط درون کارخانه ها

برای تعریف رابطه در کارخانه مدل خود، معمولاً یک نمونه کارخانه جدید را به کلید خارجی رابطه اختصاص می دهید. این معمولاً برای روابط "معکوس" مانند belongsTo و morphTo روابط انجام می شود. به عنوان مثال، اگر می خواهید هنگام ایجاد یک پست یک کاربر جدید ایجاد کنید، می توانید موارد زیر را انجام دهید:

use App\Models\User;
 
/**
* Define the model's default state.
*
* @return array<string, mixed>
*/
public function definition(): array
{
return [
'user_id' => User::factory(),
'title' => fake()->title(),
'content' => fake()->paragraph(),
];
}

اگر ستون‌های رابطه به کارخانه‌ای بستگی دارد که آن را تعریف می‌کند، می‌توانید یک بسته را به یک ویژگی اختصاص دهید. بسته شدن آرایه ویژگی ارزیابی شده کارخانه را دریافت می کند:

/**
* Define the model's default state.
*
* @return array<string, mixed>
*/
public function definition(): array
{
return [
'user_id' => User::factory(),
'user_type' => function (array $attributes) {
return User::find($attributes['user_id'])->type;
},
'title' => fake()->title(),
'content' => fake()->paragraph(),
];
}

بازیافت یک مدل موجود برای روابط

اگر مدل‌هایی دارید که رابطه مشترکی با مدل دیگری دارند، می‌توانید از این recycle روش برای اطمینان از بازیافت یک نمونه از مدل مرتبط برای همه روابط ایجاد شده توسط کارخانه استفاده کنید.

Airline به عنوان مثال، تصور کنید ، Flight مدل‌هایی دارید Ticket که در آن بلیط متعلق به یک شرکت هواپیمایی و یک پرواز است و پرواز نیز متعلق به یک شرکت هواپیمایی است. هنگام ایجاد بلیط، احتمالاً همان خط هوایی را برای بلیط و پرواز می خواهید، بنابراین می توانید یک نمونه از خطوط هوایی را به روش ارسال کنید recycle :

Ticket::factory()
->recycle(Airline::factory()->create())
->create();

recycle اگر مدل‌هایی متعلق به یک کاربر یا تیم مشترک دارید، ممکن است این روش را بسیار مفید بدانید .

این recycle روش مجموعه ای از مدل های موجود را نیز می پذیرد. هنگامی که مجموعه ای به recycle روش ارائه می شود، زمانی که کارخانه به مدلی از آن نوع نیاز دارد، یک مدل تصادفی از مجموعه انتخاب می شود:

Ticket::factory()
->recycle($airlines)
->create();