Kontynuacja kursu Laravela, w którym zboczyliśmy nieco w temat SQL, bo bez dobrej znajomości SQLa trudno jest zrozumieć w pełni to, co robi za nas ORM Laravela.

Ok, rzućmy okiem na ten kod:

CREATE TABLE `contacts` ( 
     id BIGINT  UNSIGNED NOT NULL AUTO_INCREMENT,
     person_id BIGINT  UNSIGNED NOT NULL,
     city VARCHAR(255) NOT NULL,
     street VARCHAR(255) NOT NULL,
     PRIMARY KEY(id)
    );

Mamy tutaj pierwszy constraint, czyli not null. Jeżeli go mamy, wartość nie może być nullable. Trochę odwrotnie niż w Laravelu, który ten not null dopisuje do każdej kolumny, chyba że określimy inaczej, np. ->nullable().

Ok, default czyli inny constraint:

CREATE TABLE Orders (
    ID int NOT NULL,
    OrderNumber int NOT NULL,
    OrderDate date DEFAULT CURRENT_DATE()
);

W Laravelu jak dodawaliśmy kolumnę do istniejącej tabeli, a ta kolumna nie była ->nullable, to zawsze musieliśmy jej dodać ->default($value).

Ok, unique constraint:

CREATE TABLE Persons (
    ID int NOT NULL UNIQUE,
    LastName varchar(255) NOT NULL,
    FirstName varchar(255),
    Age int
);

Swoją drogą tutaj mamy taki kolumnowy constraint (ja go nazywam inline constraint), ale są i tabelkowe:

CREATE TABLE Persons (
    ID int NOT NULL,
    LastName varchar(255) NOT NULL,
    FirstName varchar(255),
    Age int,
    UNIQUE (ID)
);

Działanie jest to samo (choć można podać kilka kolumn tam w nawiasach), po prostu inaczej to wygląda. Constraint może też być nazwany:

CREATE TABLE Persons (
    ID int NOT NULL,
    LastName varchar(255) NOT NULL,
    FirstName varchar(255),
    Age int,
    CONSTRAINT UC_Person UNIQUE (ID,LastName)
);

Jak widać nazwany, tabelkowy nie (jedno)kolumnowy inline, obejmuje kilka kolumn na raz.

Warto pamiętać, że unique constraint aby zadziałał tworzy indeks, zatem aby go usunąć robimy takie coś:

ALTER TABLE Persons
DROP INDEX UC_Person;

Choć w niektórych wersjach SQLa zrobimy to tak:

ALTER TABLE Persons
DROP CONSTRAINT UC_Person;

Dla porównania: dodanie defaulta (który jest constraintem, ale nie tworzy indeksu):

ALTER TABLE Persons
ALTER City SET DEFAULT 'Sandnes';

Już to robiliśmy, podobnie jak dropnięcie defaulta:

ALTER TABLE Persons
ALTER City DROP DEFAULT;

Samo dodanie unique jest bardzo łatwe:

ALTER TABLE Persons
ADD UNIQUE (ID);

Możemy też dodać nazwane:

ALTER TABLE Persons
ADD CONSTRAINT UC_Person UNIQUE (ID,LastName);

Ok, teraz Laravel. Jak dropnąć unique z kolumny:

$table->dropUnique('tablename_column_unique');

A teraz jak sprawić, aby kolumna wcześniej unique przestała nią być:

$table->integer('user_id')->unique(false)->change();

Samo dodanie pola z unique jest bardzo proste:

Schema::table('users', function (Blueprint $table) {
    $table->string('email')->unique();
});

W Laravelu domyślnie każda kolumna ma not null. Dodanie kolumny nullable jest proste i intuicyjne:

Schema::table('users', function (Blueprint $table) {
    $table->string('email')->nullable();
});

Zmiana (modyfikacja) kolumny z nullable na not null też jest prosta, wykorzystujemy ->change:

$table->string('foo')->nullable(false)->change();

Metodę ->change() możemy używać do modyfikacji innych rzeczy w już istniejących kolumnach:

Schema::table('users', function (Blueprint $table) {
    $table->string('name', 50)->change();
});

Oczywiście musimy pamiętać, że jak modyfikujemy to musimy przepisać całość ze zmodyfikowaną zawartością:

Schema::table('users', function (Blueprint $table) {
    $table->integer('votes')->unsigned()->default(1)->comment('my comment')->change();
});

Tu nie wiem, co zostało zmodyfikowane, bo nie znam poprzednich migracji (może nazwa, może komentarz, może default). Ale przypomnijmy sobie jak działa modyfikacja w SQL:

ALTER TABLE MyTable 
CHANGE COLUMN foo bar VARCHAR(32) NOT NULL FIRST;

Też w sumie nie wiadomo, czy mamy tu tylko rename (z foo na bar) czy varchar zmienił ilość znaków, czy not null poprzednio był a może zmiana to tylko nazwa i first?

Powinniśmy już powoli ogarniać jak to się dzieje i nie dziwić się nazbyt.