Jedna zo zmien v Laravel 8 bola prepracovanie model factories, čo viedlo k zaradeniu factories do namespace-ov. Seedery sú tiež rovnako ovplyvnené, ale to je iná téma na neskôr.
Nevenoval som dosť pozornosti tomu, aby som pochopil, prečo bola táto zmena zavedená alebo dokonca potrebná, ale je na samom vrchu zoznamu zmien s vysokým dopadom, takže som sa rozhodol hrať podľa pravidiel.
Len niekoľko dní po začatí používania som hľadal spôsob, ako efektívne generovať viacero záznamov s one-to-one vzťahom. Možno som hľadal zlé kľúčové slová, alebo jednoducho planéty neboli zarovnané, ale všetky riešenia, ktoré som našiel, vyzerali príliš komplikovane. To sa zmenilo, keď som narazil na túto skromnú odpoveď na StackOverflow, kde bolo prezentované presne správne riešenie. Pozrime sa naň.
Brloh (Lair) #
Pre brloh sú väčšina súborov úplne holé kosti, dajú sa použiť priamo tak,
ako ich vygeneruje Artisan. Maj na pamäti, že toto má byť minimálny
(dúfajme) funkčný príklad. Mohli by sme tu neskôr pridať vzťah hasOne,
ale pre samotný príklad to nie je potrebné.
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class Lair extends Model {
}
Migrácia je tiež holé kosti, ale pre skutočný brloh by sme pravdepodobne pridali nejaké stĺpce, ako napríklad názov hory, na ktorej sa nachádza.
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreateLairsTable extends Migration {
public function up() {
Schema::create('lairs', function (Blueprint $table) {
$table->id();
$table->timestamps();
});
}
public function down() {
Schema::dropIfExists('lairs');
}
}
Vyššie uvedené platí aj pre factory, priamo z generátora. Keďže sme nepridali žiadne špecifické stĺpce, netreba tu fabulovať žiadne hodnoty.
<?php
namespace Database\Factories;
use Illuminate\Database\Eloquent\Factories\Factory;
use App\Models\Lair;
class LairFactory extends Factory {
protected $model = Lair::class;
public function definition() {
return [
//
];
}
}
Drak (Dragon) #
Tu je prvý dôležitý detail, stĺpec lair_id označujúci cudzí kľúč.
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreateDragonsTable extends Migration {
public function up() {
Schema::create('dragons', function (Blueprint $table) {
$table->id();
$table->foreignId('lair_id')->constrained();
$table->timestamps();
});
}
public function down() {
Schema::dropIfExists('dragons');
}
}
Model pre Draka obsahuje vzťah belongsTo. Hoci by príklad fungoval aj bez
tejto metódy, je tu preto, aby naznačil, že v krajine môže byť mnoho
Brlohovov, ale ak existuje nejaký Drak, musí bývať v jednom z nich.
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use App\Models\Lair;
class Dragon extends Model {
use HasFactory;
public function lair() {
return $this->belongsTo(Lair::class);
}
}
A napokon sľúbená factory. Opäť takmer holé kosti s jedným riadkom navyše:
<?php
namespace Database\Factories;
use Illuminate\Database\Eloquent\Factories\Factory;
use App\Models\Lair;
use App\Models\Dragon;
class DragonFactory extends Factory {
protected $model = Dragon::class;
public function definition() {
return [
'lair_id' => Lair::factory()
];
}
}
Konkrétne ide o tento riadok:
'lair_id' => Lair::factory()->create()->id
Výsledkom vyššie uvedeného je, že teraz môžeme naraz generovať mnoho Drakov
pomocou DragonFactory takto:
<?php
use App\Models\Dragon;
//
Dragon::factory(200);
Tu by mal každý Drak vygenerovaný svoj vlastný Brloh. Treba poznamenať, že podobný prístup by mohol byť použitý aj v Laravel 7 a nižšie, ale tu som chcel vyjadriť zmeny namespace-ov, ktoré priniesol Laravel 8. Pohodlné.