الکوئنت: کارخانه ها
معرفی
هنگام آزمایش برنامه یا نمایش پایگاه داده خود، ممکن است لازم باشد چند رکورد را در پایگاه داده خود وارد کنید. به جای تعیین دستی مقدار هر ستون، لاراول به شما امکان می دهد مجموعه ای از ویژگی های پیش فرض را برای هر یک از مدل های 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();