Poznamy dzisiaj lepiej koncepcję klucza głównego i wreszcie zrozumiemy czym jest to id w naszych tabelach Laravela. Do dzieła.
Ok, co nam robi ID? Ten kawałek kodu w migracji:
Schema::create('movies', function (Blueprint $table) {
$table->id();
Rzućmy okiem na widok w tabeli mysql, czym jest to id. Wchodzimy w phpMyAdmin w bazę danych, tabelę i structure.
I widzimy, że jest to BIGINT(20) UNSIGNED null na „nie” i jakiś auto increment. Zobaczymy też indeks primary z algorytmem btree oraz (w tabeli movies) także indeks movies_title_unique.
Ok, po kolei:
- bigint 20 to liczba o określonej wielkości
- unsigned czyli ujemne wartości nie są akceptowane
- null na nie, czyli nie może być id nullable
- auto_increment, czyli sam rośnie, zaraz to sobie wytłumaczymy
- indeks primary czyli elementy często będą indeksowane (dużo operacji pobierania) poprzez tę kolumnę
- algorytm btree nadaje się do porównywania
- indeks unique na kolumnie title jest w zupełnie innym celu, jest to constraint żeby dwa takie same tytuły nie były
Ok, stwórzmy sobie bazę danych (klikiem) a potem tabelę, już z palca, nie ma łatwo:
CREATE TABLE `users` (
id BIGINT(20) UNSIGNED NOT NULL,
name VARCHAR(255) NOT NULL,
age INT UNSIGNED NOT NULL,
PRIMARY KEY(id)
);
Czy rozumiemy co tu się dzieje?
- id, name i age to nazwy kolumn
- bigint(20) to typ bigint, taki sam jakiego laravel używa do zapisywania numerów id
- unsigned to atrybut do typów numerycznych, który mówi, że minusowych nie przyjmujemy
- not null sprawia, że nullable jest false
- name varchar(255) to odpowiednik $table->string(’name’) z domyślną długością 255
- primary key id oznacza „utwórz indeks typu primary key dla kolumny id, po tej kolumnie często będą rekordy przeszukiwane, będzie to porównywane, musi być indeks na to”
Ok, dodajmy kilka rekordów:
INSERT INTO `users`
(id, name, age)
VALUES
(1, "John Doe", 33);
INSERT INTO `users`
(id, name, age)
VALUES
(2, "Jane Doe", 23);
INSERT INTO `users`
(id, name, age)
VALUES
(3, "Jim Doe", 23);
Mega denerwujące jest to ręczne dodawanie numerów ID. Dlatego stworzymy nową tabelę:
CREATE TABLE `people` (
id BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT,
name VARCHAR(255) NOT NULL,
age INT UNSIGNED NOT NULL,
PRIMARY KEY(id)
);
I teraz dodamy sobie rekordy:
INSERT INTO `people`
(name, age)
VALUES
("John Doe", 33);
INSERT INTO `people`
(name, age)
VALUES
("Jane Doe", 33);
INSERT INTO `people`
(name, age)
VALUES
("Jim Doe", 33);
Wystarczyło tylko ten AUTO_INCREMENT dodać i już mamy problem z głowy, SQL pamięta i sam dodaje co trzeba.
Ok, a teraz od drugiej strony – a gdybyśmy tak nie chcieli korzystać z table->id? Jak to odtworzyć? Tutaj mamy odpowiedź z internetu:
Schema::table('migrations', function (Blueprint $table) {
$table->bigIncrements('id')->first();
});
Podaję tylko ze względu na first, bo to ciekawa metoda, sprawia, że kolumna będzie pierwsza w tabeli.
Cóż, co nam zrobi taki kod?
$table->bigInteger('id', true, true);
Utworzy BIGINT(20), AUTO_INCREMENT (pierwsze true) UNSIGNED (drugie true). To oczywiście nie wszystko, jeszcze trzeba utworzyć indeks, mało tego, skoro bawimy się w ten sposób to jeszcze w modelu musimy dookreślić to i owo.
To i owo zależy od tego jak się bawimy, jeżeli będziemy chcieli mieć indeks tekstowy, to trzeba to zapisać w modelu, jeżeli inna nazwa niż id tak samo.
Swoją drogą nie musimy aż tak kombinować, aby mieć kolumnę id o innej nazwie:
$table->id("my_custom_id");
I jeszcze w modelu:
class Flight extends Model
{
/**
* The primary key associated with the table.
*
* @var string
*/
protected $primaryKey = 'my_custom_id';
}
Mi bardziej chodziło o to, abyśmy rozumieli wszystkie zawiłości zagadnienia klucza głównego.
Ok, gdybyśmy wytworzyli klucz główny bez auto increment to w modelu jeszcze musimy:
class Flight extends Model
{
/**
* Indicates if the model's ID is auto-incrementing.
*
* @var bool
*/
public $incrementing = false;
}
A gdyby typ klucza był inny to:
class Flight extends Model
{
/**
* The data type of the primary key ID.
*
* @var string
*/
protected $keyType = 'string';
}
Pamiętamy że linijka:
$table->id();
Równoznaczna jest z :
CREATE TABLE `tablename` (
id BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT,
//(...)
PRIMARY KEY(id)
);
Zaś linijka:
$table->bigInteger('id', true, true);
//lub
$table->unsignedBigInteger('id', true);
//lub
$table->bigInteger("id", true)->unsigned();
//lub
$table->bigIncrements('id');
luźno odpowiada:
CREATE TABLE `tablename` (
id BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT,
//(...)
);
Pewności nie mamy, że indeks utworzy, to musimy mieć na uwadze, ale jak już tak się bawimy, to bez problemu to ogarniemy w dokumentacji, choć gra niewarta świeczki moim zdaniem.