Introductie
Database-migraties zouden ruwe database-queries of Laravels Query Builder (DB-facade) moeten gebruiken in plaats van Eloquent-models. Hoewel het handig kan lijken om models te gebruiken voor datamanipulatie tijdens migraties, kan deze werkwijze na verloop van tijd leiden tot kapotte migraties en onvoorspelbaar gedrag.
Waarom
- Models evolueren, migraties niet - Wanneer je een Eloquent-model wijzigt (velden toevoegen, casting aanpassen, relaties wijzigen), weerspiegelt het model alleen de huidige staat, niet de historische staat. Een migratie die dat model gebruikt, kan mislukken wanneer deze op een schone database wordt uitgevoerd.
- Schema-mismatch tijdens uitvoering - Eloquent verwacht dat het databaseschema overeenkomt met de modeldefinitie. Tijdens migraties is het schema in beweging, wat tot fouten kan leiden wanneer een model verwijst naar velden of relaties die nog niet bestaan.
- Onvoorspelbare migratievolgorde - Als migratie 1 een model gebruikt dat wijzigingen uit migratie 2 weerspiegelt, breekt migratie 1 omdat migratie 2 nog niet is uitgevoerd.
- Scheiding van verantwoordelijkheden - Migraties zijn specifiek ontworpen voor databasestructuur, niet voor objectgestuurde datamanipulatie. Het gebruik van de DB-facade behoudt deze scheiding.
- Stabiliteit op lange termijn - Migraties moeten voor onbepaalde tijd reproduceerbaar zijn. Het gebruik van models breekt deze garantie zodra het model verandert.
Geschikt voor
- Alle migraties - Gebruik Query Builder of ruwe SQL voor elke datamanipulatie in migraties
- Data seeden tijdens migraties - Gebruik de DB-facade in plaats van models om initiële data te vullen
- Schemawijzigingen - Gebruik altijd de Schema Builder voor structurele wijzigingen
- Verse installaties - Zorgt ervoor dat migraties correct worden uitgevoerd in nieuwe omgevingen, ongeacht modelwijzigingen
Minder geschikt voor
- Database seeders - Seeders zijn bedoeld voor testdata en kunnen veilig Eloquent-models gebruiken, omdat ze apart worden uitgevoerd en geen deel uitmaken van de migratiegeschiedenis
- Eenmalige scripts - Voor scripts die niet opnieuw worden uitgevoerd, kan het gebruik van models acceptabel zijn (hoewel nog steeds niet aanbevolen)
Voorbeelden
❌ Slecht - Een Eloquent-model gebruiken:
use App\Models\Post;
public function up()
{
Schema::table('posts', function (Blueprint $table) {
$table->boolean('is_published')->default(false);
});
// This will break if the Post model changes
Post::query()->update(['is_published' => true]);
}
✅ Goed - De Query Builder gebruiken:
use Illuminate\Support\Facades\DB;
public function up()
{
Schema::table('posts', function (Blueprint $table) {
$table->boolean('is_published')->default(false);
});
// This will always work
DB::table('posts')->update(['is_published' => true]);
}
✅ Goed - Ruwe SQL gebruiken:
use Illuminate\Support\Facades\DB;
public function up()
{
Schema::table('posts', function (Blueprint $table) {
$table->boolean('is_published')->default(false);
});
// Raw SQL is also reliable
DB::statement('UPDATE posts SET is_published = true');
}