Blok 3 · rozdział 9

Lista i karta szczytu z bazy

Kontroler nie trzyma już tablicy. Lista i karta czytają modele. Gdy zmienisz wysokość w phpMyAdmin, po odświeżeniu strony zobaczysz nową wartość. Pliku Blade nie ruszasz.

Po tym rozdziale powinieneś umieć

  • pobrać szczyty z pasmem i posortować je malejąco po wysokości;
  • podmienić w Blade nawiasy tablicy na właściwości obiektu;
  • otworzyć kartę po slugu dzięki wiązaniu modelu;
  • wytłumaczyć, po co jest with('pasmo').

1. Lista z modelu

Na górze kontrolera: use App\Models\Szczyt;. Metoda index:

public function index()
{
    $szczyty = Szczyt::query()
        ->with('pasmo')
        ->orderByDesc('wysokosc_m')
        ->get();

    return view('szczyty.index', [
        'szczyty' => $szczyty,
    ]);
}

Metodę listaSzczytow() usuń, gdy formularz planu też będzie czytał modele. Inaczej w projekcie zostaną dwa źródła wysokości.

2. Obiekt zamiast tablicy

W komponencie karta-szczytu:

@props(['szczyt'])

<a class="karta" href="{{ route('szczyty.show', $szczyt) }}">
    <h2>{{ $szczyt->nazwa }}</h2>
    <p class="meta">
        {{ $szczyt->pasmo->nazwa }}
        · <span class="wysokosc">{{ $szczyt->wysokosc_m }} m</span>
    </p>
</a>

route('szczyty.show', $szczyt) wstawi slug, gdy model powie, że kluczem adresu jest slug (następny podrozdział). To samo -> zastosuj w formularzu planu: $szczyt->slug, $szczyt->nazwa. Opcje selecta bierz z tej samej kolekcji $szczyty co lista.

Pusta lista @forelse zostaje. Gdy seeder nie poszedł, użytkownik widzi „Brak szczytów”, a nie błąd o tablicy.

3. Karta i slug

W modelu Szczyt:

public function getRouteKeyName(): string
{
    return 'slug';
}

Trasa i metoda:

Route::get('/szczyty/{szczyt}', [SzczytController::class, 'show'])->name('szczyty.show');
public function show(Szczyt $szczyt)
{
    $szczyt->load('pasmo');

    return view('szczyty.show', [
        'szczyt' => $szczyt,
    ]);
}

Laravel sam czyta fragment adresu, szuka wiersza WHERE slug = … i podaje obiekt. Brak wiersza kończy się 404 bez Twojej pętli. W widoku karty: $szczyt->nazwa, $szczyt->pasmo->nazwa, $szczyt->wysokosc_m, $szczyt->opis.

Wiązanie modelu w trasie Typ Szczyt przy argumencie metody mówi Laravelowi: ten kawałek URL to rekord tej tabeli. Nazwa parametru {szczyt} i nazwa zmiennej $szczyt mają być zgodne.

Wejdź na /szczyty/rysy i na /szczyty/nie-ma. Potem w phpMyAdmin zmień wysokość Łysicy o 1 metr, odśwież listę, przywróć 614.

4. with('pasmo')

Bez with('pasmo') lista 28 szczytów zrobiłaby jedno zapytanie o szczyty i kolejne 28 o pasma — przy każdym $szczyt->pasmo w pętli. To nazywa się problemem N+1. with('pasmo') dociąga pasma jednym dodatkowym zapytaniem.

Warto umieć powiedzieć „Lista bierze się z Szczyt::query() w index. Pasmo jest relacją belongsTo. Widok tylko wypisuje właściwości.”
Commit

Gdy lista i karta czytają bazę, a zły slug daje 404:

git add .
git status
git commit -m "Lista i karta z bazy"

Przed commitem git status nie pokazuje .env.