Witaj w moim świecie! Dziś na warsztat bierzemy coś, co na pierwszy rzut oka wygląda jak zbawienie, a w rzeczywistości jest koniem trojańskim w Twoim kodzie. Mowa o dyrektywie @inject w Blade.

Pewnie widziałeś artykuły, które ją zachwalają. “Czyste kontrolery!”, “Mniej kodu!”, “Elegancja!”. Brzmi super, prawda? Sam kiedyś tak myślałem. Ale po latach walki w okopach Laravela, powiem Ci jedno: używanie @inject to proszenie się o kłopoty.

Co to w ogóle jest @inject?

Dla niewtajemniczonych, @inject to sprytny sposób, by wstrzyknąć serwis z kontenera Laravela prosto do widoku. Zamiast robić to w kontrolerze, robisz to w pliku .blade.php:

{{-- Gdzieś w Twoim widoku --}}
@inject('stats', 'App\Services\StatisticsService')

<p>Liczba postów: {{ $stats->getPostCount() }}</p>

Twój kontroler staje się chudy jak przecinek. Magia! Ale to iluzja, która drogo kosztuje.

Architektoniczny koszmar w przebraniu

Wyobraź sobie, że Twoja aplikacja to restauracja:

  • Kontroler to szef kuchni. On wie, co, jak i z czego przygotować.
  • Widok (Blade) to kelner. Jego zadaniem jest podać gościowi to, co przygotował szef kuchni. Ma wyglądać ładnie i apetycznie.

Używając @inject, każesz kelnerowi biegać po kuchni i samemu szukać składników. Nagle Twój kelner, zamiast serwować dania, zaczyna grzebać w lodówkach i przyprawach. Chaos gwarantowany.

Mieszając logikę z prezentacją, tworzysz kod, który jest:

  1. Trudny do testowania: Jak przetestować logikę, która jest zaszyta w widoku? To jak próbować ocenić smak zupy, patrząc na zdjęcie w menu.
  2. Nieprzewidywalny: Gdzie te dane są w ogóle używane? Musisz przeszukiwać pliki .blade.php, żeby znaleźć logikę biznesową. Powodzenia za pół roku!
  3. Mało elastyczny: Chcesz użyć tej samej logiki w API? Albo w konsoli? Ups… jest przyklejona do widoku. Trzeba pisać od nowa.

Jak to zrobić dobrze? Dwa proste sposoby

Zamiast iść na skróty, użyj narzędzi, które Laravel daje Ci od lat. Są sprawdzone w boju i nie zrobią Ci krzywdy.

Sposób 1: Stary, dobry kontroler (90% przypadków)

To najprostsze i najlepsze rozwiązanie. Niech kontroler robi swoją robotę.

// PostController.php
public function show(Post $post, StatisticsService $stats)
{
    $postCount = $stats->getPostCount();

    return view('posts.show', [
        'post' => $post,
        'postCount' => $postCount,
    ]);
}

// posts/show.blade.php
<p>Liczba postów: {{ $postCount }}</p>

Proste, czytelne, testowalne. Każdy wie, gdzie co jest.

Sposób 2: View Composers (gdy dane są wszędzie)

Jeśli jakieś dane (np. liczba powiadomień, menu) muszą być dostępne w wielu widokach, użyj View Composers. To dedykowani “pomocnicy”, którzy przygotowują dane dla widoków.

Definiujesz klasę, która zbiera dane:

// app/View/Composers/NotificationComposer.php
class NotificationComposer
{
    public function compose(View $view)
    {
        $view->with('unreadNotifications', auth()->user()->unreadNotifications()->count());
    }
}

I mówisz Laravelowi, kiedy ma jej użyć (np. w AppServiceProvider):

// AppServiceProvider.php
public function boot()
{
    View::composer('partials.nav', NotificationComposer::class);
}

Teraz każdy widok partials.nav dostanie zmienną $unreadNotifications. Centralne zarządzanie, zero bałaganu.

Podsumowując: Nie idź na skróty

@inject to jedna z tych funkcji, które brzmią dobrze w teorii, ale w praktyce prowadzą do kodu, którego nikt nie chce utrzymywać.

Pamiętaj o złotej zasadzie: kontrolery kontrolują, widoki wyświetlają.

Trzymaj się jej, a Twoje aplikacje będą solidne, łatwe w rozwoju i przyjemne w pracy. A Ty będziesz spać spokojnie, nie martwiąc się o ukrytą logikę w swoich widokach.

Masz inne zdanie? Zostaw komentarz! Chętnie podyskutuję. A jeśli ten post Ci pomógł, zajrzyj tu za jakiś czas po więcej praktycznych porad od starego wyjadacza.