7 β Database va migratsiyalar¶
β¬ οΈ Oldingi: 06 β Request va Response Β· π README Β· Keyingi: 08 β Eloquent ORM β asoslar β‘οΈ
Bu bobda: ma'lumotni qayerda saqlaymiz degan savoldan boshlaymiz.
.envorqali bazani ulashni (tez boshlash uchun SQLite, yoki haqiqiy loyiha uchun MySQL), so'ng asosiy mavzu β migration'larni o'rganamiz: baza strukturasini qo'lda SQL yozmasdan, PHP kod bilan, jamoa bilan izchil boshqarishni.make:migration, schema builder (ustun turlari,foreignId,enum),up()/down()metodlari,migrate/rollback/fresh/refreshbuyruqlari, tashqi kalitlar (constrained, cascade), indekslar (unique,index) va mavjud jadvalga ustun qo'shish/o'zgartirishni ko'rib chiqamiz.
Muammo¶
Aytaylik, blog loyihasini yozyapsiz. Sizga maqolalar jadvali kerak: sarlavha, matn, chop etilgan-etilmaganligi. Eski usul bo'yicha siz phpMyAdmin'ni ochib, qo'lda SQL yozardingiz:
CREATE TABLE maqolalar (
id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
sarlavha VARCHAR(255),
matn TEXT,
chop_etilgan TINYINT(1) DEFAULT 0
);
Ishladi. Lekin endi haqiqiy hayot boshlanadi:
- Ertaga jamoadosh Dilshod loyihaga qo'shildi. U ham aynan shu jadvalni o'z kompyuterida yaratishi kerak. Siz unga bu SQL'ni qayerdan berasiz? Telegram'dami? Esidan chiqib qolsa-chi?
- Keyingi haftada
korishlarustuni kerak bo'ldi. Kim qaysi ustunni qo'shganini, qachon qo'shganini qayerda yozib boriladi? - Serverga (production) chiqarganda xuddi shu o'zgarishlarni u yerda ham bir-bir takrorlash kerak. Bittasi unutilsa β "column not found" xatosi.
Muammoning ildizi: baza strukturasi kod emas, shuning uchun u Git'da yo'q, jamoada tarqaladi, esdan chiqadi. Kod fayllaringiz Git'da versiyalanadi-yu, baza tuzilishi havoda osilib qoladi.
Laravel'ning yechimi β migration (migratsiya): baza strukturasini oddiy PHP fayl sifatida yozasiz. Bu fayl Git'da turadi, jamoaning hammasida bir xil bo'ladi, va bitta buyruq bilan har qanday kompyuterda yoki serverda ishga tushadi. Migration β bu baza uchun versiya nazorati, xuddi Git fayllar uchun bo'lganidek.
Avval baza: .env sozlash¶
Laravel'ga "qaysi bazaga ulanaman" deb aytishingiz kerak. Bu sozlamalar loyiha ildizidagi .env faylida turadi (6-bobda ko'rgan muhit fayli).
Variant A β SQLite (tez boshlash uchun tavsiya)¶
SQLite β bu butun bir baza bitta faylda. Hech narsa o'rnatmaysiz, server ishlatmaysiz: shunchaki bitta .sqlite fayl. O'rganish va kichik loyihalar uchun ideal. Laravel 11+ da yangi loyiha default holatda SQLite bilan keladi:
Qolgan DB_* qatorlarni (host, port, parol) o'chirib tashlasangiz ham bo'ladi β SQLite'ga ular kerak emas. Baza fayli database/database.sqlite da turadi. Agar u hali yo'q bo'lsa, bo'sh fayl sifatida qo'lda yarating:
π Windows'da touch bo'lmasligi mumkin β PowerShell'da New-Item database/database.sqlite yoki muharrirda bo'sh database.sqlite faylini yarating. Yangi Laravel loyihasini ochishda SQLite tanlasangiz, installer bu faylni o'zi yaratadi β bunda qo'lda yaratish ham shart emas.
Variant B β MySQL (haqiqiy loyiha uchun)¶
Agar MySQL o'rnatgan bo'lsangiz (yoki Laravel Herd/Sail ishlatsangiz), .env shunday bo'ladi:
π DB_DATABASE β bu baza nomi, va bu bazaning o'zi avval mavjud bo'lishi kerak. Laravel jadvallarni yarata oladi, lekin bo'sh bazani odatda siz qo'lda yaratasiz: MySQL'da CREATE DATABASE blog;. (SQLite'da esa bu muammo yo'q β fayl o'zi baza.)
π‘ Boshlovchi sifatida bemalol SQLite'dan boshlang. Sintaksis va migration'lar ikkalasida ham bir xil β keyinroq .env da bitta qatorni o'zgartirib MySQL'ga o'tasiz, kodingizni umuman tegmaysiz. Bu Laravel'ning kuchli tomoni: kodingiz baza turidan deyarli mustaqil.
Ulanish ishlayotganini tekshirish uchun:
Agar baza haqida ma'lumot chiqsa β ulanish to'g'ri. Xato chiqsa, .env dagi sozlamalarni qayta tekshiring (ko'pincha parol yoki baza nomi).
Migration nima β sekin tushunamiz¶
Yangi Laravel loyihasini ochsangiz, database/migrations/ papkasida allaqachon bir nechta fayl turibdi (foydalanuvchilar, cache, jobs uchun). Demak, Laravel'ning o'zi ham migration'lardan foydalanadi.
Migration fayli ikki narsani biladi:
up()β "oldinga": jadval yaratadi yoki o'zgartiradi.php artisan migratechaqirilganda shu ishlaydi.down()β "orqaga":up()qilgan ishni bekor qiladi (odatda jadvalni o'chiradi).php artisan migrate:rollbackchaqirilganda shu ishlaydi.
Ya'ni har bir migration β bu ikki tomonlama qadam: ham qo'shadi, ham qaytarib oladi. Bu g'oyani sof PHP'da imitatsiya qilib ko'raylik (Laravel'siz, faqat tushunish uchun):
<?php
abstract class Migration {
abstract public function up(): void;
abstract public function down(): void;
}
$baza = [];
$migration = new class($baza) extends Migration {
public function __construct(private array &$baza) {}
public function up(): void {
$this->baza['kitoblar'] = ['id', 'nomi', 'narx'];
echo "up(): 'kitoblar' jadvali yaratildi\n";
}
public function down(): void {
unset($this->baza['kitoblar']);
echo "down(): 'kitoblar' jadvali o'chirildi\n";
}
};
$migration->up(); // 'kitoblar' qo'shildi
$migration->down(); // 'kitoblar' o'chirildi
Natija:
Haqiqiy Laravel migration'i aynan shu shaklda: Migration klassini meros oladigan anonim klass (return new class extends Migration), ichida up() va down(). Faqat massiv o'rniga haqiqiy bazani o'zgartiradi. Siz PHP'dan anonim klassni bilasiz β bu yangi narsa emas.
π Nega anonim klass? Migration fayllari ko'p (har biri o'z faylida), va ularga nom (klass nomi) berish shart emas β Laravel ularni fayl nomi orqali biladi. Shuning uchun Laravel 9 dan beri ular nomsiz (anonim) klass sifatida yoziladi.
Birinchi migration: make:migration¶
Endi haqiqiy ish. Blog uchun maqolalar jadvalini yaratamiz. Avval bo'sh migration faylini generatsiya qilamiz:
Natija:
INFO Migration [database/migrations/2026_06_11_100000_create_maqolalar_table.php] created successfully.
E'tibor bering:
- Fayl nomi oldida sana va vaqt turadi (
2026_06_11_100000). Bu β migration'larning tartibi. Laravel ularni shu sana bo'yicha ketma-ket ishga tushiradi. Shuning uchun "avvalmaqolalar, keyin unga bog'liqizohlar" tartibi avtomatik saqlanadi. create_..._tablenomidan Laravel aqlli taxmin qiladi: "bu yangi jadval yaratish" deb, faylga tayyorSchema::create('maqolalar', ...)shabloni soladi.
π‘ Nom berishda Laravel konvensiyasiga rioya qiling: yangi jadval uchun create_<jadval>_table, mavjudini o'zgartirish uchun add_<ustun>_to_<jadval>_table yoki change_..._in_..._table. Jadval nomi β ko'plik va kichik harf (maqolalar, users), chunki Eloquent (8-bob) shu konvensiyaga tayanadi.
Schema builder: jadvalni kod bilan chizamiz¶
Yaratilgan faylni ochsak, ichida shunday bo'ladi. Uni to'ldiramiz:
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
public function up(): void
{
Schema::create('maqolalar', function (Blueprint $table) {
$table->id();
$table->string('sarlavha');
$table->text('matn');
$table->boolean('chop_etilgan')->default(false);
$table->integer('korishlar')->default(0);
$table->timestamp('chop_sana')->nullable();
$table->timestamps();
});
}
public function down(): void
{
Schema::dropIfExists('maqolalar');
}
};
Bu yerda nima bo'lyapti, qator-qator:
Schema::create('maqolalar', function (Blueprint $table) { ... })β "maqolalarnomli jadval yarat, uning ustunlarini mana shu funksiya ichida e'lon qilaman".$tableβ bu sizning "qalamingiz", jadvalga ustun chizadigan asbob (Blueprint).$table->id()βidnomli avtomatik o'sadigan birlamchi kalit (primary key). Har doim birinchi yoziladi.$table->string('sarlavha')βVARCHAR(255)ustun (qisqa matn). Uzunlikni o'zgartirsangiz:$table->string('sarlavha', 100).$table->text('matn')βTEXTustun (uzun matn, masalan maqola tanasi).$table->boolean('chop_etilgan')->default(false)βtrue/falseustun, standart qiymatifalse.$table->timestamp('chop_sana')->nullable()β sana-vaqt ustuni;nullable()"bo'sh (NULL) bo'lishi mumkin" degani.$table->timestamps()β bu bitta chaqiruv ikkita ustun yaratadi:created_atvaupdated_at. Laravel ularni avtomatik to'ldiradi (yozuv yaratilganda va yangilanganda). Deyarli har jadvalda bo'ladi.
π down() da nima bo'lishini diqqat bilan o'ylang: up() jadval yaratgan bo'lsa, down() uni o'chirishi kerak (dropIfExists). Qoida: down() har doim up() ning teskarisi. Buni to'g'ri yozmasangiz, rollback ishlamaydi.
Ustun turlari xaritasi¶
Eng ko'p ishlatiladigan metodlar va ular bazada hosil qiladigan ustun turi:
enum β qiymati cheklangan ro'yxatdan biri bo'lishi shart bo'lgan ustun:
Endi bu ustunga faqat shu uch qiymatdan biri yoziladi β boshqasini yozmoqchi bo'lsangiz, baza rad etadi.
π‘ Ustunni "majburiy emas" qilish uchun zanjirga ->nullable() qo'shing; standart qiymat berish uchun ->default(...). Bu metodlarni zanjirlash (chaining) mumkin: $table->string('telefon')->nullable()->default(null).
Ishga tushiramiz: php artisan migrate¶
Migration faylini yozdik β lekin bazada hali hech narsa yo'q. Fayl shunchaki "reja". Uni bajarish uchun:
Natija:
Mana endi maqolalar jadvali bazada haqiqatan paydo bo'ldi. Laravel sizning PHP kodingizni ichida CREATE TABLE ... SQL'iga aylantirib, bazaga yubordi. Siz bironta SQL yozmadingiz.
π Laravel qaysi migration'lar allaqachon ishlaganini eslab qoladi β buning uchun u bazada migrations nomli maxsus jadval ochadi. Shuning uchun migrate'ni qayta chaqirsangiz, eski migration'lar takror ishlamaydi; faqat yangi (hali ishlamagan) fayllar bajariladi. Bu jamoada juda muhim: Dilshod loyihani klon qilib php artisan migrate desa, bir zumda butun baza strukturasi unda ham paydo bo'ladi β hech qanday qo'lda SQL yo'q.
Asosiy migration buyruqlari¶
| Buyruq | Nima qiladi |
|---|---|
php artisan migrate |
Hali ishlamagan migration'larni ishga tushiradi (up()) |
php artisan migrate:rollback |
Eng oxirgi "partiya"ni orqaga qaytaradi (down()) |
php artisan migrate:rollback --step=1 |
Faqat 1 ta oxirgi migration'ni qaytaradi |
php artisan migrate:fresh |
HAMMA jadvalni o'chirib, noldan qayta yaratadi |
php artisan migrate:refresh |
Hammasini rollback qilib, qaytadan migrate qiladi |
php artisan migrate:status |
Qaysi migration ishlagan-ishlamaganini ko'rsatadi |
Ikki muhim farqni ajratamiz:
migrate:rollbackβdown()metodlaringizdan foydalanadi (ularni teskari tartibda chaqiradi). Agardown()xato yozilgan bo'lsa, rollback ham sinadi.migrate:freshβdown()ga umuman qaramaydi. Shunchaki bazadagi barcha jadvallarni o'chirib tashlaydi vaup()larni boshidan yuradi. Tez va ishonchli, lekin butun ma'lumotni yo'q qiladi.
β οΈ migrate:fresh va migrate:refresh butun ma'lumotni o'chiradi. Bu rivojlanish bosqichida ajoyib (struktura o'zgardimi β migrate:fresh deb noldan tiklaysiz). Lekin production serverida HECH QACHON ishlatmang β real foydalanuvchilar ma'lumotini bir lahzada yo'q qiladi.
π‘ Rivojlanish paytida migration'ni o'zgartirsangiz (masalan ustun nomini), eng oson yo'l β faylni tahrirlab, php artisan migrate:fresh qilish. Allaqachon ishlagan migration faylini tahrirlab, oddiy migrate qilsangiz β hech narsa o'zgarmaydi, chunki Laravel "bu fayl ishlagan" deb biladi va uni qayta ishlatmaydi. Yangi boshlovchilar shu yerda ko'p adashadi.
π Production'da ma'lumotni saqlab qolib struktura o'zgartirish kerak bo'lsa β migrate:fresh emas, yangi migration yoziladi (pastdagi "ustun qo'shish" bo'limiga qarang). Bu β to'g'ri yo'l.
Foreign key β jadvallarni bog'lash¶
Blogimizda endi izohlar (kommentariyalar) jadvali kerak. Har bir izoh qaysidir maqolaga tegishli. SQL kursidan (yoki PHP'dagi mantiqdan) bilasiz: bog'lanish tashqi kalit (foreign key) orqali bo'ladi β izohlar jadvalida maqola_id ustuni maqolalar jadvalining id siga ishora qiladi.
Laravel buni juda chiroyli qiladi:
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
public function up(): void
{
Schema::create('izohlar', function (Blueprint $table) {
$table->id();
$table->foreignId('maqola_id')->constrained()->cascadeOnDelete();
$table->foreignId('user_id')->constrained();
$table->text('matn');
$table->timestamps();
});
}
public function down(): void
{
Schema::dropIfExists('izohlar');
}
};
Ikkita yangi tushuncha bor:
$table->foreignId('maqola_id')βBIGINT UNSIGNEDustun yaratadi. Bu βid()bilan bir xil tur, chunki u boshqa jadvalningidsiga mos kelishi kerak.->constrained()β "bu ustunni haqiqiy tashqi kalit qil". Laravel ustun nomidan (maqola_id) jadval nomini taxmin qiladi:maqola-> ko'plikmaqolalar-> uningidustuniga bog'la. Sehr emas, qat'iy konvensiya:<jadval_birlik>_id-><jadvallar>.id.->cascadeOnDelete()β "agar maqola o'chirilsa, unga tegishli izohlar ham avtomatik o'chsin". Bu cascade (zanjirli o'chirish).
π Tartib muhim! izohlar migration'i maqolalar migration'idan keyin ishlashi shart β chunki bog'lanish uchun maqolalar jadvali allaqachon mavjud bo'lishi kerak. Bu o'z-o'zidan to'g'ri bo'ladi: make:migration'ni maqolalar uchun avval, izohlar uchun keyin chaqirgansiz, demak fayl nomidagi sana ham shunday tartibda.
Agar nom konvensiyaga mos kelmasa¶
->constrained() taxmin qila olmasa (masalan ustun muallif_id, lekin jadval users), jadval nomini o'zingiz aytasiz:
onDelete xatti-harakatini boshqa usulda ham yozsa bo'ladi (ikkalasi bir xil):
Boshqa variantlar: ->nullOnDelete() (ota o'chsa, maqola_id ni NULL qiladi), ->restrictOnDelete() (izohi bor maqolani o'chirishga umuman yo'l qo'ymaydi).
π‘ Qaysi birini tanlash mantiqqa bog'liq. Izoh maqolasiz mantiqsiz β demak cascadeOnDelete(). Lekin, masalan, "buyurtma"ni o'chirsangiz, "mijoz"ni o'chirib bo'lmaydi (mijozning boshqa buyurtmalari bor) β bu yerda restrictOnDelete() to'g'riroq.
Indekslar: unique va index¶
Ikki muammoni hal qilamiz.
1-muammo: takrorlanmaslik. Foydalanuvchilar jadvalida ikki kishi bir xil email bilan ro'yxatdan o'tmasligi kerak. Buni baza darajasida kafolatlash uchun unique:
Endi baza bir xil email'ni ikki marta yozishga yo'l qo'ymaydi β ikkinchi urinishda xato qaytaradi. Bu validatsiyadan (12-bob) ham kuchliroq himoya, chunki u baza darajasida: hatto kodda xato bo'lsa ham, takror yozilmaydi.
2-muammo: tezlik. Agar slug ustuni bo'yicha tez-tez qidirsangiz (WHERE slug = '...'), unga index qo'ying β baza qidiruvni tezlashtiradi (kitobning mundarijasi kabi):
Bir nechta ustunni birgalikda noyob qilish (kompozit unikal) β masalan bir foydalanuvchi bir maqolaga faqat bir marta ovoz bersin:
To'liq misol:
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
public function up(): void
{
Schema::create('foydalanuvchilar', function (Blueprint $table) {
$table->id();
$table->string('email')->unique();
$table->string('telefon')->nullable();
$table->string('slug');
$table->enum('rol', ['admin', 'muharrir', 'oddiy'])->default('oddiy');
$table->index('slug');
$table->timestamps();
});
}
public function down(): void
{
Schema::dropIfExists('foydalanuvchilar');
}
};
π unique ham aslida bir turdagi indeks β u ham qidiruvni tezlashtiradi, ham takrorlanishni taqiqlaydi. Farqi: index faqat tezlik uchun, takrorlashga ruxsat beradi; unique esa qo'shimcha ravishda takrorlashni man qiladi.
Mavjud jadvalga ustun qo'shish va o'zgartirish¶
Eng tez-tez uchraydigan vaziyat: loyiha ishlab turibdi, baza to'la, va sizga yangi ustun kerak bo'lib qoldi. Eski migration faylini tahrirlamaysiz (u allaqachon ishlagan, qaytib ishlamaydi, qolaversa serverdagi ma'lumotni yo'qotib qo'yasiz). To'g'ri yo'l β yangi migration:
Bu safar create emas, Schema::table (mavjud jadvalni o'zgartirish):
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
public function up(): void
{
Schema::table('maqolalar', function (Blueprint $table) {
$table->string('qisqacha', 200)->nullable()->after('sarlavha');
$table->boolean('tavsiya')->default(false);
});
}
public function down(): void
{
Schema::table('maqolalar', function (Blueprint $table) {
$table->dropColumn(['qisqacha', 'tavsiya']);
});
}
};
Schema::table(...)βcreateemas: mavjud jadvalga qo'shimcha kiritadi.->after('sarlavha')β yangi ustun qaysi ustundan keyin tursin (MySQL'da; SQLite buni e'tiborsiz qoldiradi).down()dadropColumnbilan qo'shgan ustunlarni olib tashlaymiz β yana o'sha qoida:down()=up()teskarisi.
So'ng odatdagidek:
Faqat shu yangi migration ishlaydi, mavjud ma'lumot saqlanib qoladi, jadvalga ikki yangi ustun qo'shiladi.
Ustunni o'zgartirish va nomini almashtirish¶
Mavjud ustun turini o'zgartirish uchun ->change(), nomini almashtirish uchun renameColumn:
public function up(): void
{
Schema::table('maqolalar', function (Blueprint $table) {
$table->string('sarlavha', 250)->change(); // 255 -> 250
$table->renameColumn('matn', 'tana'); // ustun nomi
});
}
π ->change() ustunning to'liq yangi ta'rifini talab qiladi. Ya'ni agar ustun avval nullable bo'lgan bo'lsa va siz ->change() da nullable() yozmasangiz, u NOT NULL ga aylanib qoladi. Shuning uchun change() da ustunning hamma xususiyatlarini qayta yozing, faqat o'zgartirmoqchi bo'lgan qismni emas.
π‘ down() ni ham mos yozing: change() da eski turiga qaytaring (250 -> 255), renameColumn da nomni teskari almashtiring (tana -> matn). Aks holda rollback bazani noto'g'ri holatga keltiradi.
Hammasini birlashtirib: tipik ish oqimi¶
Kundalik amalda migration bilan ishlash quyidagicha ko'rinadi:
- Yangi jadval/ustun kerak bo'ldi ->
php artisan make:migration ... - Faylni ochib,
up()(va albattadown()) ni yozasiz. php artisan migrateβ bazaga qo'llaysiz.- Xato qildingizmi yoki strukturani o'zgartirmoqchimisiz (rivojlanishda) ->
php artisan migrate:rollbackyokiphp artisan migrate:fresh. - Tayyor bo'lsa β migration faylni Git'ga commit qilasiz. Endi butun jamoa va server xuddi shu strukturani bir buyruq bilan oladi.
π Migration β bu Eloquent (8-bob) bilan ishlashning poydevori. Migration jadval strukturasini yaratadi; Eloquent esa o'sha jadval bilan PHP obyektlari orqali ma'lumot almashadi. Avval skelet (migration), keyin jon (Eloquent). 8-bobda aynan shu maqolalar jadvalini Eloquent model bilan jonlantiramiz.
β
To'g'ri: har struktura o'zgarishi uchun yangi migration; down() doim yoziladi; jadval nomi ko'plik; FK uchun foreignId(...)->constrained().
β Xato: phpMyAdmin'da qo'lda jadval yaratish; ishlagan migration'ni tahrirlash; down() ni bo'sh qoldirish; production'da migrate:fresh.
7-bob mashqlari¶
Quyidagi mashqlarni o'zingiz bajaring β yechimlari berilmagan. Yangi Laravel loyihasida (yoki o'rganish loyihasida) ishlang. Avvalgilari yengil, asta-sekin qiyinlashadi.
-
Yangi Laravel loyihasida
.envfaylini ochib,DB_CONNECTION=sqliteqilib sozlang vatouch database/database.sqlite(yoki Windows'daNew-Item database/database.sqlite) bilan bo'sh baza faylini yarating.php artisan migrateni ishga tushirib, default jadvallar yaratilganiga ishonch hosil qiling. -
.envda bazani MySQL'ga o'tkazib sozlang (DB_CONNECTION=mysqlva qolganDB_*qiymatlari).php artisan db:showbilan ulanishni tekshiring. (MySQL yo'q bo'lsa, bu mashqni o'qib chiqing va SQLite'da davom eting.) -
php artisan make:migration create_kitoblar_tablebuyrug'i bilan migration yarating. Yaratilgan faylni toping va fayl nomi oldidagi sana-vaqt nima uchun kerakligini bir jumlada izohlab yozing. -
kitoblarjadvaliga quyidagi ustunlarni qo'shing:id,nomi(string),tavsif(text),sahifalar(integer),mavjud(boolean, default true),timestamps. So'ngphp artisan migrateqiling. -
down()metodidaSchema::dropIfExists('kitoblar')borligiga ishonch hosil qiling. So'ngphp artisan migrate:rollbackqilib, jadval o'chganini, qaytaphp artisan migrateqilib, qayta yaratilganini kuzating. -
kitoblarjadvaliganarxustuninidecimal('narx', 8, 2)sifatida qo'shing (hujjatdandecimalmetodini izlang). Migration'ni qayta yarating yokimigrate:freshqiling. -
nomiustunini majburiy emas (nullable) qilib, default qiymatinullbo'ladigan qilib o'zgartiring. Buning uchun yangi migration emas,migrate:freshdan oldin asl migration faylini tahrirlang. -
Yangi
mualliflarjadvali yarating:id,ism(string),davlat(string, nullable),timestamps. -
kitoblarjadvaligamuallif_idustuniniforeignId(...)->constrained()bilan qo'shing, shunda umualliflarjadvaliga bog'lansin. Migration tartibiga (qaysi avval ishlashi kerak) e'tibor bering. -
9-mashqdagi tashqi kalitga
cascadeOnDelete()qo'shing. So'ng Tinker'da (php artisan tinker) bitta muallif va unga bog'liq kitob yaratib, muallifni o'chirib, kitob ham o'chganini tekshiring. -
kitoblarjadvaligaisbn(string) ustuniniunique()bilan qo'shing. Bir xil ISBN'ni ikki marta kiritishga urinib, baza xato qaytarishini kuzating. -
kitoblarjadvaligaslugustunini qo'shib, ungaindex()qo'ying. Indeks nima uchun kerakligini ikki jumlada izohlang. -
kitoblarjadvaligaholatnomlienumustun qo'shing:['mavjud', 'tugagan', 'buyurtmada'], default'mavjud'. Ro'yxatda yo'q qiymat kiritishga urinib ko'ring. -
Yangi migration yozib (
add_..._to_kitoblar_table),kitoblarjadvaligachegirma(integer, default 0) ustuniniafter('narx')bilan qo'shing. Faqat shu migration ishlaganinimigrate:statusbilan tasdiqlang. -
14-mashqdagi migration uchun
down()metodinidropColumnbilan to'g'ri yozing, so'ngmigrate:rollback --step=1bilan faqat shu ustunni olib tashlang. -
kitoblarjadvalidaginomiustuninirenameColumnorqalisarlavhaga o'zgartiruvchi migration yozing.down()da teskari almashtirishni ham yozing. -
kitoblarjadvalidaginomiustun turinistring('nomi', 100)danstring('nomi', 250)ga->change()orqali o'zgartiring.change()da ustunning barcha xususiyatlarini qayta yozish nega zarurligini izohlang. -
Ikki ustunli kompozit unikal indeks yarating: yangi
baholarjadvalida (foydalanuvchi_id,kitob_id) juftligi takrorlanmasin ($table->unique([...])). Bir foydalanuvchi bir kitobga ikki marta baho bera olmasligini ta'minlang. -
migrate:rollbackvamigrate:freshfarqini amalda ko'rsating: ikkalasini ham ishlatib, qaysi biridown()ga tayanishini, qaysi biri hamma jadvalni o'chirishini yozma tushuntiring. Nega production'damigrate:freshxavfli ekanini ham qo'shing. -
To'liq mini-loyiha:
kategoriyalar(id, nomi) vamahsulotlar(id, nomi, narx decimal,kategoriya_id-> constrained + cascade,faolboolean,slugunique,holatenum, timestamps) jadvallari uchun ikkita migration yozing. To'g'ri tartibdamigrateqiling, so'ngmigrate:freshbilan butun strukturani noldan qayta tiklang vamigrate:statusbilan hammasini tasdiqlang.