Uczymy się jak tworzyć komponenty Laravela oraz przede wszystkim po co nam one są potrzebne i czy ich potrzebujemy. Ścisła kontynuacja kursu Laravela oraz Vue.js.
Ok, najpierw po co. Cóż, jeżeli chcemy robić aplikację typowo backendową, bez żadnego reaktywnego frontendu to po nic. Komponenty to po prostu overkill i niepotrzebne utrudnienie w takim wypadku.
Nawet odchodzi się od głównego layoutu jako komponentu (ktoś pamięta jeszcze x-layout?) na rzecz dziedziczenia layoutów. Więc jeśli apka tylko backendowa, to komponenty nam nie są potrzebne, wprowadzają dodatkowe utrudnienie, kod jest przesadne rozsiany w zbyt wielu miejscach i wystarczy nam po prostu dobrze pisać widoki i podwidoki.
Jeżeli chcemy apki reaktywnej i napaliliśmy się mocno na to Vue.js albo znamy Reacta – również nam komponenty Blade nie są potrzebne. Inertia JS zapewni nam (razem z vite i jakimś starter kitem, Breeze najłatwiejszy) bezproblemową integrację Vue/Reacta z Laravelem.
Te frameworki frontendowe mają własne komponenty i komponenty Blade są wtedy zbędne.
Może jednak być tak, że napaliliśmy się na to Vue, jednak z pozycji bardziej PHPowca, jak zobaczyliśmy jak wyglądają „prawdziwe” komponenty, to się przeraziliśmy, za dużo JS, zbyt skomplikowane, pal 6 tę reaktywność.
W takim wypadku mamy Alpine JS, czyli coś dużo łatwiejszego od Vue i posiadającego kilka własnych, bardzo ciekawych użyteczności, za to bez JSowego oczopląsu. I ten Alpine możemy stosować sam w sobie (niedługo się go nauczymy) albo łączyć z komponentami Blade, które są napisane w PHP, używając frameworku Laravel, czyli bardziej znanego nam stosu technologicznego.
Ok, czy chcemy iść w Alpine i Blade Components, czy w Vue components i więcej pisać JSa, PHP trzymać ściśle do backendu, to już nasza decyzja. Ja tylko pokazuję, jak je robić.
Dobra, projekt w Laravelu, rzućmy okiem na ten kod:
Route::get('/person/{id}', function (Request $request, $id) {
$person = Person::findOrFail($id);
return Blade::render(
'Fullname: {{ $person->full_name }} </br>
Age: {{$person->age}} </br>
Created_at: {{$person->created_at}}
', ['person' => $person]);
});
Dodamy sobie name, będziemy potrzebować:
Route::get('/person/{id}', function (Request $request, $id) {
$person = Person::findOrFail($id);
return Blade::render(
'Fullname: {{ $person->full_name }} </br>
Age: {{$person->age}} </br>
Created_at: {{$person->created_at}}
', ['person' => $person]);
})->name('person.singleRecord');
Ok, tworzymy komponent komendą:
php artisan make:component Person
W App\View\Components odnajdujemy i definiujemy propsy:
class Person extends Component
{
/**
* Create a new component instance.
*/
public function __construct(
public readonly string $name,
public readonly int $id,
){}
/**
* Get the view / contents that represent the component.
*/
public function render(): View|Closure|string
{
return view('components.person');
}
}
Constructor-promotion, type-hinting, readonly fields. Jak nas przeraża, to chyba jednak lepiej postawić na Vue.
Dobra, teraz idziemy do widoków, folder components, plik person.blade.php:
<div>
<li>
<a href="{{route('person.singleRecord', $id)}}">
<b>Name:</b>{{$name}} <b>ID</b>: {{$id}}
</a>
</li>
</div>
Teraz gdzieś sobie tego użyć musimy:
Route::get('/people/byagedesc', function (Request $request) {
$ppl= Person::orderBy('age', 'desc')->get();
return Blade::render(
'<ul>
@forelse($people as $person)
<x-person :id="$person->id" :name="$person->firstName"/>
@empty
<li>Nothing found</li>
@endforelse
</ul>', ['people' => $ppl]);
});
Brzydko to wygląda, ale z doświadczenia wiem, że lepiej używać metod, które są „obskurne” (jak Blade::render) niż tłumaczyć godzinę jaki plik gdzie utworzyć. Lekcja ma być prosta, mamy sobie przekopiować, przeanalizować, zobaczyć że działa, przeanalizować raz jeszcze a potem użyć tego „po Bożemu”, czyli kontroler, view, x-person w odpowiednim miejscu…
Ale tak to wygląda. Komponenty są tworzone w ten sposób. Reaktywność zaś będzie robić nam Alpine. Obejrzyjmy sobie w ramach zadania domowego dokumentację Alpine.
I tak będzie kurs Alpine już niedługo. Ale nam nikt nie każe uczyć się wszystkiego na raz. Musimy zdecydować, albo Vue i pełen JS na frontendzie, albo komponenty z Blade, wspomagane Alpine.
PS. Oczywiście nic nie stoi na przeszkodzie, abyśmy wybrali backend. Jest jeszcze wiele zagadnień backendowych, z których kursu nie zrobiliśmy, choćby cache, redis, używanie local query scopes z url query stringiem w optymalny sposób (zaawansowane filtrowanie), full text search w MySQL oraz Laravelu (Scout), API (w tym kolekcje, Sanctum) i kursy z tych zagadnień niedługo wskoczą.
Natomiast najpierw będzie trochę kursów z Vue/Apline oraz InertiaJS i chciałbym, aby to wszystko złożyło się w jedną, fullstackową całość. Ale czytelnik może do woli dobierać części kursu według własnych upodobań, może się uczyć albo tylko frotnendu (a backend sobie nawet w JS robić) albo tylko backendowych technik w Laravelu/Symfony.