3. Jak działa Laravel?
Aplikacje webowe oparte o Laravela najczęściej będą:
● wystawiać widoki budowane w HTML
● obsługiwać formularze
● serwować REST API
4. Jak działa Laravel? (ale tak na serio)
Może się okazać, że wejść i wyjść jest kilka, ale my skupimy się
dziś tylko na obsłudze zapytań HTTP.
5. Biblioteka vs. framework
Warto zacząć od tego czym różni się
framework od biblioteki. Laravel jest
oczywiście frameworkiem.
Biblioteka jest częścią kodu, która może
zostać dodana do naszego kodu.
Korzystamy z wielu bibliotek, np.
Guzzle lub Elasticsearch Client.
6. Biblioteka vs. framework
Framework jest natomiast kodem, do
którego dokładamy nasz kod. Wszystkie
ważniejsze rzeczy dzieją się we
frameworku, a my konfigurujemy jedynie
aspekty związane z logika biznesową.
Zaraz to zobaczymy na przykładach.
7. No to jedziemy!
Wiemy zatem, że zapytanie HTTP będzie uderzało do naszej aplikacji
zbudowanej na Laravelu. Praktycznie wszystkimi akcjami steruje framework…
oprócz jednej, a mianowicie uruchomienia Laravela.
Entrypoint do systemu znajduje się w pliku public/index.php
8. public/index.php
W zależności od wersji index.php się będzie różnił, ale mniej więcej zawsze robi
to samo: tworzy instancję jądra Laravela i przekazuje do niego złapane
zapytanie HTTP.
9. bootstrap/app.php
Plik public/index.php odwołuje się do bootstrap/app.php. To tam tworzona jest
instancja Laravela i deklarowane są powiązania która klasa będzie miała
zostać utworzona pod który interfejs.
10. Inne entrypointy
Warto pamiętać, że plik artisan również korzysta z bootstrap/app.php
Jest to na tyle istotne, że wszelkie zadeklarowane dodatkowo providery czy
inne zmiany w public/index.php nie będą dostępne z poziomu php artisan *
11. IlluminateFoundationApplication.php
Laravel składa się z kilku(dziesięciu?)
części składowych, ale jedną z
najważniejszych są jego kontener
zależności i lista providerów.
Ich inicjalizację można podejrzeć w
IlluminateFoundationApplication.php
12. IlluminateFoundationApplication.php
Najprościej ujmując:
● do aplikacji Laravela możemy
dodawać własne service providery,
które będą modyfikowały stan
aplikacji
● do kontenera zależności, często przez
providery, możemy wpisywać
bindingi instancji do zadanych
abstrakcji
13. Bindowanie instancji
W tak łatwy sposób można powiedzieć Laravelowi, że za każdym razem, gdy
“ktoś” poprosi o gdziekolwiek o AppContractsEventPusher, kontener
zależności wyda instancję AppServicesRedisEventPusher.
14. Więc wróćmy do public/index.php
Tworzymy metodą make() instancję zbindowaną do interfejsu
IlluminateContractsHttpKernel. Z bootstrap/app.php wiemy, że będzie to…
zadeklarowany w naszej aplikacji AppHttpKernel.php!
15. IlluminateFoundationHttpKernel.php
To co istotne znajduje się w bloku try: każde zapytanie HTTP zostaje
przepuszczone przez router. Jeżeli coś złego się stanie, wywołany zostanie
handler wyjątków.
16. IlluminateFoundationHttpKernel.php
I teraz zaczyna się zabawa: Laravel binduje obiekt Request z naszym
zapytaniem do kontenera zależności. Od teraz będzie można się do niego
odezwać z prawie każdego miejsca aplikacji. Request natomiast przesyłany jest
przez zadeklarowane middlewary i dopiero przesyłany do routera.
17. Ale jakie middlewary?
Wystarczy zajrzeć do naszego app/Http/Kernel i zbadać jego pole $middleware.
Powinna znaleźć się tam tablica middlewarów, które zostaną nałożone na
każde zapytanie. Może być ich dowolna liczba, mogą dowolnie działać.
Na przykład fajnie można sobie identyfikować wszystkie obiekty Request:
18. Ale jakie middlewary?
Warto też pamiętać, że Laravel umożliwia definiowanie nie tylko klasycznych
“before middlewarów”, ale także może nieco mniej intuicyjne “after
middleware”:
20. Magia!
Tutaj zaczyna się mocno skomplikowana rzecz. Metoda dispatch() wywołuje
dispatchToRoute(), która z kolei po wywołaniu findRoute() wywołuje
runRoute().
findRoute() szuka wzoru z zapytania HTTP w dostarczonych mu routach. A
skąd je zna? Możemy jest zadeklarować w service providerze, a konkretnie w
app/Providers/RouteServiceProvider.php - to tam deklarujemy jak podpiąć
routes/web.php czy routes/api.php
A więc znów cała magia dzieje się we frameworku, a po naszej stronie zostaje
włożenie odpowiedniego klocka w odpowiednie miejsce.
21. IlluminateRoutingRoute.php
Po zbudowaniu kolejnego Pipeline’a z middlewarami, router będzie spróbował
stworzyć kontroler, do którego jest przypisany dopasowany route. Metoda run()
sprawdzi jak została zarejestrowana akcji route’a i spróbuje coś z nią zrobić.
W przypadku powyżej, obsłużony zostaje klasyczny route podpięty pod
kontroler.
23. IlluminateRoutingControllerDispatcher.php
Na tak stworzonym kontrolerze jest wywoływana metoda… również
wykoncypowana z konfiguracji. Natomiast resolveClassMethodDependencies()
to nic innego jak wywołanie refleksją wszystkich parametrów metody
kontrolera… znowuż w kontenerze zależności.
24. FormRequesty?
FormRequest, czyli z góry określony schemat oczekiwanego zapytania HTTP to
jeden z najwygodniejszych bulbulatorów Laravela. Wystarczy dodać nazwę
klasy Form Requestu do sygnatury metody kontrolera i nagle walidacja
zaczyna “sama działać” wedle opisanych reguł. Ale jak to działa?
25. FormRequesty?
Nikt w routerze nie sprawdza na twardo typów tworzonych obiektów. W taki
sposób plik Route.php rozrósłby się do dziesiątek tysięcy linijek kodu w
wielkim ifowym drzewku.
Ale przecież mamy kontener zależności! W IlluminateFoundationProviders
FormRequestServiceProvider zadeklarowano hook, który mówi, że po
wybraniu każdego obiektu implementującego kontrakt IlluminateContracts
ValidationValidatesWhenResolved, zostanie na nim wywołana metoda
validateResolved()
A co w niej jest? Ano walidacja naszego Form Requestu!
26. Jak działa Laravel?
A na samym końcu tak naprawdę możemy stworzyć jeden
kontroler, podpiąć go pod domyślny router i wszystko będzie
działać.
27. Słówko przestrogi
Takiej “magii” w Laravelu jest bardzo dużo. Bardzo.
Warto przejść się z debuggerem i krok po kroku zobaczyć jak wyglądają
przedstawione tutaj procesy, ale także wszystkie inne: tłumaczenia, fasady,
korzystanie z konfiguracji.