Ahogy arra a cím is utal, főleg az útvonal fájlunkban
(routes/web.php), illetve a nézet fájljainkban (resources/views
mappában) fogunk tevékenykedni.
Mielőtt rátérnék, hogy hogyan is lehet adatokat átadni a nézeteknek, még két egyszerű dolgot próbáljunk ki:
- az
első amikor az útvonal visszatérése még nem egy konkrét nézet, hanem
csak egy szöveg. Például a főoldal útvonalánál egy sima return 'Hello
world' utasítást írjunk meg és próbáljuk ki a főoldal lekérését.
- másodszor
próbáljuk ki azt, amikor nem csak egy sima szöveggel, hanem egy tömbbel
térünk vissza ugyanott. Például így: return ['foo' => 'bar']; -->
ekkor a böngészőben egy JSON-t kapunk vissza és az itt definiált
értéket. Érdemes a böngészőben különböző fejlesztői kiegészítést
használni, és akkor nem csak a JSON fájl tartalmát tudjuk megtekinteni,
hanem a válasz (response) fejléc részét is, amiben látjuk, hogy a
Content-Type egy json típusú fájl. Ez nagyon hasznos akkor, ha mondjuk
egy API-t akarunk összeállítani.
Info: PHP-ban is léteznek tömbök, ugyanúgy ahogy a többi programozási nyelvben is. Az imént mi egy úgynevezett asszociatív tömböt használtunk, amikor nem egész számot alkalmazunk a tömbindexekhez (0, 1, 2, ...), hanem valamilyen szöveges értéket.
Arról, hogy mi is a JSON fájl, itt lehet olvasni bővebben.
Számunkra talán első körben elég most annyit tudni, hogy ez egy
szöveges fájl, amelyben adatokat tudunk tárolni kulcs-érték párok
segítségével. Amiért nagyon jók ezek a fájlok, az főleg az
egyszerűségükből adódik, valamint hogy mindkét oldalon (kliens és
szerver részen is) egyszerűen tudjuk kezelni és feldolgozni őket.
Korábban erre az XML fájltípust használták, azonban az eléggé bonyolult
is tud lenni, aminek nehézkessé válhat a kezelése, úgyhogy mindenképpen
inkább a JSON használatát javaslom.
Ennyi kis bevezető után,
térjünk rá a mostani fő témánkra, az adatok átadására a nézeteknek.
Maradjunk az iménti példa "útvonalán", vagyis először egy szöveges
változóban lévő adatot adjunk át az útvonalon keresztül a nézetnek.
Info: PHP-ban a változóneveket mindig $ jellel kezdjük.
$username = 'Attila';
return view('welcome', [
'name' => $username
]);
Vegyük észre, hogy továbbra is a view()
segédfüggvényt használjuk, amiben az 1. paraméter a nézet neve lesz, míg
a 2. paraméter egy asszociatív tömb (erre utal a szögletes zárójel []
páros), amiben a 'name' kulcshoz, hozzárendeljük a $username érték párt.
Ez volt tehát az első rész, ahol az útvonalnál elküldjük az adatot, már
csak a nézetben megkapott adatot kell kiírni a felhasználónak.
A
welcome nézetben a változóban lévő adat kiíratását elvégezhetjük
többféle módon. Kezdjük a kicsit ódivatú PHP-s kiíratással, aztán majd
megnézzük a modern Blade-es kiíratást is. Ahova pedig kiírjuk, az
bárhova lehetne, de én a content osztályú div-en belül a title osztályú
div-be teszem a kiíratást.
Szia <?php echo $name; ?>
Ez igazából egy nagyon régies megoldás, sokan nem is szeretik emiatt a
PHP-t, mert a kvázi HTML fájlba ilyen módon tele lehet pakolni PHP
kódokkal. A PHP kódot karakterekkel kell lezárni. Az echo az pedig egy
sima kiíratást jelent, a $name változó kiíratását. Vegyük azért észre a
mindig hangsúlyozott névkonvenciót. Amit küldtünk adatot az útvonal
fájlból, az egy asszociatív tömb volt (kulcs-érték pár), ebből a
nézetben a kulcsra tudunk hivatkozni és azt megjeleníteni a
felhasználónak. Ennél a fenti megoldásnál egy fokkal elegánsabb, de még
mindig csak egy "sima" PHP-s kiíratás van itt:
Szia <?= $name; ?>
Sűrűn előfordult az, hogy egy-egy kiíratásra használták csak a PHP-s
beágyazást a kvázi HTML kódba, emiatt ezt az egyszerűsített formát is
lehet alkalmazni (ekvivalens a fenti megoldással). Viszont mi egy Blade
fájlt használunk, ami még egyszerűbbé teszi az életünket, úgyhogy a
kiíratásra bőven elég csak ezt használnunk:
Szia {{ $name }}
A kiíratásokat kipróbálhatjuk egymás után a böngészőben, mindig ilyen eredményt kell kapnunk:
Köszönthetünk persze mást is, itt én saját magamnak írtam egy sziát. :-)
Most
már működik a változó kiíratása, ezért most következhet egy tömb
kiíratása. Először elküldjük a tömb adatait egy új útvonalnak, aztán
majd rátérünk a nézetes megjelenítésre. A web.php-ban regisztráljuk az
új útvonalat:
Route::get('/arraytest', function () {
$tasks = [
'Go to the store',
'Go to the market',
'Go to the work'
];
return view('arraytest', [
'tasks' => $tasks
]);
});
Az útvonal neve arraytest, ebben definiáljunk egy $tasks nevű tömböt,
ami három szöveges elemből áll. Utána pedig, a korábban látott módon a
view() segédmetódus második paraméterében adjuk át ezt a tömböt, vagyis
küldjük el az arraytest nevű nézetnek. Ez eddig oké, azonban ha most a
böngészőben le szeretnénk kérni a localhost:8000/arraytest útvonalat,
akkor hibát kapnánk, de szerencsére egy jó beszédes hibát, ami arra
utal, hogy nincs még arraytest nevű nézetünk, amire a view
segédmetódusban hivatkoztunk. Hozzuk ezért létre a resources/views
mappában az arraytest.blade.php nevű fájlt. Létrehozás után pedig
következhet a kiíratás, amit most is "hagyományosan" fogunk először
megtenni:
<ul>
<?php foreach($tasks as $task) : ?>
<li><?= $task; ?></li>
<?php endforeach; ?>
</ul>
Info: HTML-ben a "pöttyös" felsorolást az ul tag-gel tudunk csinálni, a benne lévő felsorolási pontokat pedig az li tag-gel tudjuk megcsinálni. Itt egy foreach-es
ciklust tudunk alkalmazni, amivel a kapott tömbön végig tudunk lépkedni
és annyi felsorolási pontot teszünk bele, amennyi elem van a kapott
tömbben.
Így nézne ki a hagyományos php-s kiíratás a nézetben…
azonban nekünk a Blade nézetrendszer segítséget nyújt és
egyszerűsítéseket tudunk végrehajtani (az ul tag-eket meghagyhatjuk
ugyanúgy):
@foreach($tasks as $task)
<li><?= $task; ?></li>
@endforeach
A "háttérben" a fordító tudja, hogy emögött az egyszerűsítés mögött a
fenti kód van. A @foreach magját is tovább tudom egyszerűsíteni, ami
ugye fenn egy sima PHP-s kiíratásnak felelt meg:
<li>{{ $task }}</li>
Sokkal-sokkal egyszerűbb lett így a kód. A weboldal frissítgetésével
folyamatosan ellenőrizhetem, hogy még mindig jól jelenik-e meg, amit én
szerettem volna. Ez a kódsorozat ugye nem csak egyszerűbb, de sokkal
könnyebben is olvasható, mint ahonnan elindultunk.
Ha bővítem a
web.php-ban a nézetnek átadott $tasks tömböt, akkor az az új elem is
rögtön megjelenik a weboldalon egy frissítés után: például adjuk hozzá
ezt az új szöveges elemet: 'Task #4' és teszteljük is. Szerencsére
működik, úgyhogy örülünk. Egy módon még teszteljük a tömbös adatátadást.
Térjünk vissza a web.php-ra és módosítsuk a return utasítást az
arraytest útvonalnál:
return view('arraytest')->withTasks($tasks);
A with() segédmetódus lesz itt a segítségünkre,
amellyel "hozzáfűzhetjük" a nézethez az adatainkat, fent például a
$tasks tömbünket. De megtehetjük ugyanezt egy változóval is, ami talán
jobban rávilágít a használatának mikéntjére:
$foobar = 'foobar';
return view('arraytest')->withTasks($tasks)->withFoo($foobar);
A "with"-hez hozzáírt nevet tudjuk a nézetekben felhasználni a
kiíratásra. Így tehát a nézetben $foo változót (kis kezdőbetűs) tudjuk
kiíratni, aminek az értéke 'foobar' lesz, mivel a paraméterül megkapott
változó értéke lesz benne.
Össze is vonhatjuk a "with utáni részeket" a with() segédmetódus segítségével:
return view('arraytest')->with([
'foo' => $foobar,
'tasks' => $tasks
]);
A továbbiakban megismerkedünk egy újabb segédmetódussal, amit a Laravel keretrendszerben használhatunk. Ez a request()
metódus lesz, amivel felhasználói bemeneteket, adatokat (input-okat)
tudunk lekezelni. Hozzunk létre ennek is egy új útvonalat, majd az ehhez
kapcsolódó nézetet is ugyanúgy (bár ez egyáltalán nem elvárás) requesttest névvel.
Route::get('requesttest', function () {
return view('requesttest', [
'title' => request('title'),
]);
});
Itt már a megjegyzésben is jeleztem, hogy hogyan lehet majd használni
a felhasználótól kapott bemenetet: az URL megfelelő
"felparaméterezésével".
Info: vegyük észre, hogy a
felhasználó által definiált paraméterek szintén kulcs-érték párokként
jelennek meg az URL-ben. A paraméterlista ? (kérdőjellel) kezdődik, majd utána a kulcs érték párok = (egyenlőségjellel) összerendelve vannak. Ha további kulcs-érték párokat is szeretnénk így megadni, akkor & (és) jellel kell összefűzni a paramétereket. Példa: utvonalnev?kulcs1=ertek1&kulcs2=ertek2&kulcs3=ertek3
Az adatátadás tehát megvan, a requesttest.blade.php-ban pedig egy sima kiíratást végzünk:
<h1>{{ $title }}</h1>
Eredménye pedig így néz ki (az URL title attribútumának átírogatásával és az oldal újratöltésével tudjuk tesztelni a megoldást):
Ez működik, azonban a háttérben több minden történik, mint csak egy
PHP-s echo-s kiíratás. Ugyanis, ha például egy javascript-et adunk meg
paraméterként mondjuk a foo tömbelemnek:
Route::get('requesttest', function () {
return view('requesttest', [
'title' => request('title'),
'foo' => '<script>alert("foobar");</script>',
]);
});
Majd a nézetben kiíratjuk a PHP-s módszerrel:
<p><?= $foo; ?></p>
Frissítsük a weboldalunkat, és vegyük észre, hogy felugrott az alert
(figyelmeztetés) ablak, amit fentebb kódoltunk. Ez egy elég nagy
biztonsági rés, hiszen a kódbeszúrásos támadások így sikeresen végre
tudnának hajtódni, ha ezt a PHP-s kiíratós módszert használnánk.
Viszont
ez "csak" PHP és még egyáltalán nem használtuk ki a Laravel (Blade)
nyújtotta lehetőségeket, úgyhogy menjünk tovább ebbe az irányba: írjuk
át "Blade-esre":
<p>{{ $foo }}
</p>
Ekkor a $foo változó kiíratásakor nem hajtódik végre a script, csak
ennek a konkrét szövegnek a kiíratása történik meg. Ez tehát egy
biztonsági elem, így védekezik a rendszer a kód beszúrásos
támadástípusok ellen.
Ha megnézzük az oldal forrását (jobb
egérgomb a weboldalon és az oldal forráskódjának megtekintése), akkor
látható, hogy a "kacsacsőr", az idézőjel átalakultak különleges HTML
karakterekre, amelyek így már másképp működnek. Ha viszont a nézetben
átalakítjuk ilyenre:
<p>{!! $foo !!}</p>
Akkor ezzel jelezzük a rendszernek, hogy egy script érkezik,
nyugodtan végrehajthatja és le fog futni az alert-ünk. De ezzel azért
nagyon-nagyon legyünk körültekintőek, óvatosak, hogy mikor és hogyan
használjuk, mert veszélyes és ha a felhasználótól érkező script-et
szeretnénk így feldolgozni, azt inkább sürgősen felejtsük el...
A
blogbejegyzés során született kódokat ezen a commit-en tudod nyomon
követni (a "felülírt" kódokat a fájlnak megfelelő megjegyzésekbe tettem,
de mindegyik kipróbálható a megjegyzések elvételével): Routing 2. rész (commit)