PHP blokkok
Ebben a leckében főként a PHP és HTML kód kapcsolatával fogunk foglalkozni, de előbb pontosabban megismerjük, hogy milyen nyelvtani szabályok alapján kell írni a ciklusokat és elágazásokat.
Utasításblokkok
Van egy olyan nyelvtani szabály, miszerint ha a különféle vezérlési szerkezetek (ciklusok, elágazások) feltétele után egyetlen utasítás áll, akkor a kapcsos zárójeleket elhagyhatjuk. A kapcsos zárójelek csak arra szolgálnak, hogy több utasítást "egyberakjunk", így az nyelvtanilag egyetlen utasításként kezelhető. Ez érvényes az if és else ágakra, a while, for és do utasításokkal szervezett ciklusokra, valamint a foreach szerkezetre egyaránt:
if ($jelszo == "joo") print "Jó a jelszó"; else exit();
while ($n < 10) print $n++;
for ($m = 0; $m < $hossz; $m++)
if ($string{$m} == "\n")
$html .= "<br />";
else
$html .= $string{$m};
do print $n++; while ($n < 10);
$napok = array("hétfő", "kedd", ...);
foreach ($napok as $sorszam => $nap)
$napok[$sorszam] = $napok[$sorszam]{0};
A programok tevékenységéről annyit, hogy a for-ciklus a $string karakterlánc alapján létrehozza a $html karakterláncot, amelyben az újsor-karakterek helyén <br /> tegek állnak. A foreach pedig a $napok tömbből csinál egy olyan tömböt, amelyben csak a karakterláncok első karakterei szerepelnek. A print $n++; egy összetett utasítás, olyasmi mint például a $tomb[$n++], vagyis kiírja $n értékét, majd eggyel növeli. A for-ciklus esetében a ciklusmag egy teljes elágazásból áll, ami azonban önmagában egyetlen utasításnak felel meg, így beágyazott szerkezetek esetén is elhagyható a kapcsos zárójel. Azért érdemes óvatosnak lenni, ha nem vagyunk biztosak benne hogy egy utasításnak felel-e meg egy bonyolultabb szerkezet, inkább rakjuk ki a zárójeleket. A switch-szerkezet esetén viszont nem hagyhatók el a zárójelek! Ha több utasítást szeretnénk rakni egy ciklusmagba, vagy egy if-else szerkezetbe, akkor össze kell fognunk őket a kapcsos zárójelekkel. A kapcsos zárójelekkel összefogott utasítások listáját szokták utasításblokknak hívni. Ha például ezt írjuk:
while ($n < 10) print $n; ++$n;
akkor a ++$n már nem lesz része a ciklusmagnak, hiába jeleztük behúzással a szándékunkat, a program ezt nem veszi figyelembe, így egy szép kis végtelen ciklust kaptunk.
Előfordulhat, hogy egy olyan ciklust sikerül írnunk, aminek a magjába nem kell semmilyen utasítás. Például várakoztatni akarjuk a program futását 5 másodpercig:
$t = time();
while (time() < $t + 5){
utasítások
}
Itt addig vizsgáljuk a time() által visszaadott értéket, amíg az kisebb, mint $t + 5, ez a feltétel pedig körülbelül 5 másodperc elteltével válik hamissá. Ha a ciklus pörgetése közben nem akarunk csinálni semmit, akkor a ciklusmagba egy üres utasítást kell raknunk, ami egy pontosvessző. Mivel ez egyetlen utasítás, a kapcsos zárójelek elhagyhatók, és nem is muszáj új sorba raknunk:
$t = time(); while (time() < $t + 5);
Az, hogy a ciklusmagban vagy az if-else szerkezetben lévő utasítást vagy utasításblokkot új sorba írjuk-e ránk van bízva, a program működése szempontjából lényegtelen, így például egy egyszerű feltételes utasítást is nyugodtan írhatunk egy sorba, ha úgy véljük, hogy az áttekinthetőséget nem rontja túlságosan:
if ($jelszo != "Joo") exit();
Konstansok
Már a 2. leckében megtanultuk, hogyan hozhatunk létre változókat. A PHP-ben lehetőség van állandók (más néven konstansok) létrehozására is, amikben szintén adatokat lehet tárolni. A változóktól abban különböznek, hogy ha egyszer értéket adtunk nekik, azt utána már nem változtathatjuk meg. További fontos különbség, hogy a konstansok nevének elején nincs $ jel, de ezt leszámítva az elnevezési szabályok megegyeznek a változókkal. Végül, egy konstans értéke csak egyszerű típus lehet (logikai érték, egész szám, lebegőpontos szám vagy karakterlánc). Vagyis nem tudunk például konstans tömböt létrehozni. Konstansokat a define() függvénnyel hozhatunk létre:
define("PI", 3.1415);
define("NEV", "Hörb");
Az első paraméter a konstans neve (karakterlánc formájában), a második pedig az értéke. Ezután a PHP kódon belül hasonlóan használhatjuk őket, mint a változókat:
$kerulet = 2 * $r * PI;
if (NEV == "Hörb"){
print "Név: ".NEV."<br />";
}
Csak értékadások bal oldalán nem állhatnak, mivel az értéküket nem változtathatjuk meg! A konstansoknak általában nagybetűs neveket szoktak adni, hogy jobban elkülönüljenek a környező kódtól, de ez nem kötelező.
Az előredefiniált változókhoz hasonlóan léteznek előredefiniált konstansok is, melyekből a legkülönfélébb információkat tudjuk kinyerni. Például a PHP_OS nevű konstansból kideríthetjük, hogy a PHP kód milyen operációs rendszer alatt fut. Ha mondjuk Windows XP alatt futtatod a wampot, akkor a konstans értéke a "WINNT" karakterlánc. De ha feltöltöd a netre, akkor nagy a valószínűsége, hogy nem ezt kapod, mivel a szervereken általában Unix vagy Linux operációs rendszert szoktak futtatni. Az előredefiniált konstansokat tömb formájában visszaadja a get_defined_constants() függvény, így ha kíváncsi vagy rájuk, kiírathatod őket például így:
print "<pre>"; print_r(get_defined_constants()); print "</pre>";
Ezeken kívül vannak úgynevezett mágikus konstansok, amik értéke attól függ, hogy hol illetve mikor használjuk őket. Általában hibakeresésre vagy hibák kijelzésére használhatóak, a nevük két aláhúzás karakterrel kezdődik és végződik. Például a __LINE__ konstans annak a sornak a sorszámát tartalmazza, amelyikben szerepel, a __FILE__ az aktuálisan futó fájl nevét. Ha hibát észlel a program, és ki akarjuk vele íratni, hogy hol a hiba, akkor azt lehet például így:
if (Valami hiba van){
print "Hiba a ".__FILE__." fájl ".__LINE__.". sorában!";
}
Ez valami ilyesmit fog kiírni:
Hiba a C:\wamp\www\proba.php fájl 4. sorában!
Azért vannak elkülönítve "mágikus" néven, mivel egy programon belül nem feltétlenül állandó az értékük, de az értéküket mi nem tudjuk befolyásolni.
PHP blokkok
PHP blokkoknak nevezik a HTML kódba beékelt <?php ... ?> tegeket, ahol a ... helyén PHP kód szerepel. Mivel eddig csak a PHP nyelvre koncentráltunk, jobbára így nézett ki egy teljes weboldal:
<html> <head> <title>PHP gyakorlás</title> </head> <body> <?php // PHP kód... ?> </body> </html>
Mivel a PHP blokk belsejét már meg tudjuk tölteni mindenféle hasznos (vagy akár haszontalan) dologgal, most foglalkozzunk azzal, hogy a HTML kódon belül hova is kellene raknunk ezeket! PHP blokkot a HTML kódon belül tulajdonképpen bárhova elhelyezhetünk, csak azt kell szem előtt tartanunk, hogy a blokkokban lévő utasítások sorban egymás után hajtódnak végre, és ez magukra a blokkokra is érvényes. Vagyis a kód végén lévő blokkba rakott PHP kód nyilván később fog lefutni, mint ami a kód elején van. Mivel a PHP és a HTML kód általában jóval hosszabb szokott lenni, mint a fenti példában látható kód, ezért érdemes arra törekedni, hogy minél kevésbé keverjük őket. Ez például többé-kevésbé elérhető, ha a PHP kód nagy részét még a teljes HTML kód elé rakjuk (a nyitó <html> teg elé), a dinamikusan kiírandó szövegeket változókba rakjuk, majd a megfelelő helyeken kiírjuk őket:
<?php // PHP kód... $title = "Cím"; $szoveg1 = "Üdv!"; $szoveg2 = "Hosszú szöveg ..."; $hatterszin = "#FF8888"; ?> <html> <head> <title><?php print $title; ?></title> </head> <body bgcolor="<?php print $hatterszin; ?>"> <h1><?php print $szoveg1; ?></h1> <p align="left"> <?php print $szoveg2; ?> </p> </body> </html>
Persze ennek így nem sok értelme van, a legfelső PHP blokkba valamilyen bonyolult kódot kell képzelni, ami előállítja a megfelelő változókat. Ezt csak példaként mutattam, nem mindig követhető ez a séma, vagy legalábbis nem mindig érdemes. Ha éppen úgy látjuk jónak, a teljes HTML kódot kiírathatjuk print-tel, és akkor az oldal egyetlen nagy PHP blokk lesz.
Ahogy a bevezetőben is említettem, amikor egy php fájlt megnyitunk a böngészővel a benne lévő PHP kód a szerveren fut le, és a böngésző a szervertől már csak a PHP kód segítségével előállított HTML kódot kapja meg. A fenti esetben például ezt:
<html> <head> <title>Cím</title> </head> <body bgcolor="#FF8888"> <h1>Üdv!</h1> <p align="left"> Hosszú szöveg ... </p> </body> </html>
A böngésző nem csak HTML kódot tud értelmezni, az általa kapott HTML kódban lehet CSS és JavaScript kód is, ezek szintén a böngészőben futnak. Ez azt jelenti, hogy ha a HTML kódba be van ágyazva CSS és JavaScript kód, akkor a PHP-vel ezekbe is belenyúlhatunk, még mielőtt a böngésző megkapná ezeket. Ezek többnyire a <head> részben szoktak előfordulni, például ilyen formában:
<html>
<head>
<title>Cím</title>
<style type="text/css">
h1 {
color: #00FF00;
text-decoration: underline;
}
</style>
<script type="text/javascript">
alert("Üdv az oldalon!");
</script>
</head>
<body>
<h1>Üdv!</h1>
</body>
</html>
A <style> és </style> tegek közötti kód CSS nyelven van írva, a <script> és </script> tegeken belüli pedig JavaScript kód. A HTML kód az oldal szerkezetét írja le, a CSS elsősorban az oldal formázására és díszítésére való, a JavaScript kóddal pedig dinamikussá tudjuk tenni a weboldalt (a JavaScript a böngészőben fut így maga az oldal lesz dinamikus, nem pedig a kód előállítása, mint a PHP esetében). A JavaScript-ről olvashatsz még az Űrlapok 4. leckéjében. A fenti CSS kódnak az lesz az eredménye, hogy minden <h1> tegbe írt szöveg zöld színű és aláhúzott lesz, a JavaScript kód pedig az oldal betöltésekor megjelenít egy párbeszédablakot, amiben az "Üdv az oldalon!" szöveg lesz. Ez ugyan elég idegesítő a látogató számára, de most nem ez a lényeg, hanem az, hogy ezekbe a kódokba is beszúrhatunk PHP blokkokat. Például:
<?php
$szin = "#00FF00";
$udvozlet = "Üdv az oldalon!";
?>
<html>
<head>
<title>Cím</title>
<style type="text/css">
h1 {
color: <?php print $szin; ?>;
text-decoration: underline;
}
</style>
<script type="text/javascript">
alert("<?php print $udvozlet; ?>");
</script>
</head>
<body>
<h1>Üdv!</h1>
</body>
</html>
Ez a fentebb látott kódot fogja eredményezni.
A PHP blokkokat félbe is lehet szakítani egy befejezetlen kódon belül, és a következő PHP blokkban lehet folytatni a kódot. Tegyük fel, hogy ezt szeretnénk előállítani:
<?php $lang = "HU"; $nev = "Hörb"; ?> ... <body> <h1>Üdv, <b><i><?php print $nev; ?></i></b>!</h1> <h1>Welcome, <b><i><?php print $nev; ?></i></b>!</h1> </body>
és ha $lang értéke "HU", akkor a fölső, ha valami más, akkor pedig az alsó sort szeretnénk megjeleníteni. Ezt lehet pl úgy, hogy print-tel íratjuk ki őket a változó értéke szerint:
<?php
$lang = "HU";
$nev = "Hörb";
?>
...
<body>
<?php
if ($lang == "HU"){
print '<h1>Üdv, <b><i>'.$nev.'</i></b>!</h1>';
}
else{
print '<h1>Welcome, <b><i>'.$nev.'</i></b>!</h1>';
}
?>
</body>
De lehet így is csinálni:
<?php
$lang = "HU";
$nev = "Hörb";
?>
...
<body>
<?php if ($lang == "HU"){ ?>
<h1>Üdv, <b><i><?php print $nev; ?></i></b>!</h1>
<?php }else{ ?>
<h1>Welcome, <b><i><?php print $nev; ?></i></b>!</h1>
<?php } ?>
</body>
vagyis egy PHP blokkot meg lehet szakítani, és a következő blokkban folytatni. Ekkor a közé írt HTML kód ugyanúgy fog viselkedni, mintha a print-tel lenne kiíratva, vagyis a $lang értékétől függően itt is csak az egyik sor fog megjelenni (jelen esetben a magyar).
Állományok beépítése
Ha már komolyabban foglalkoztál a HTML nyelvvel, akkor nyilván készítettél többoldalas weblapokat is. Ha ilyen oldalakat ezentúl szeretnél PHP kóddal kiegészíteni (vagy újraírni), akkor nyilván több php fájlból fog állni az egész weblap (ennek egyébként az "Űrlapok és fájlkezelés" rész elsajátítása után mindenképp lesz értelme, még ha most nem is látszik annyira). Ha több php fájl van, akkor ezek között alapesetben nincs semmilyen kapcsolat. Például ha írunk egy hasznos függvényt, amit több fájlban is fel szeretnénk használni, akkor minden php fájlba be kell raknunk a definícióját. A függvény ugyanis az adott php fájlon belül használható, amiben a definíciója szerepel. PHP használata esetén azonban van lehetőség arra, hogy egy fájl tartalmát beépítsük a kódba. Erre az include() függvény használható:
<?php
include("functions.php");
...
?>
Az include()-nak egy paramétere van, ahova egy fájl relatív elérési útját kell beírni, ahol a relatív azt jelenti, hogy ahhoz a fájlhoz képest kell megadni az elérési utat, amelyben a függvényt hívjuk. A fenti esetben az include() hívásának a hatása olyan lesz, mintha a functions.php fájl tartalmát bemásolnánk a helyére. Így ha abba gyűjtjük össze az általunk írt függvényeket, akkor azt ezután bármelyik php fájlba beépíthetjük, és használhatjuk a benne lévő függvényeket. Mivel egy PHP függvény hívása csak PHP blokkon belül történhet, ezért természetesen a fájl kiterjesztésének, amibe beépítjük a használni kívánt állományt, php-nek kell lennie. A beépítendő állománynak azonban nem kell php fájlnak lennie, lehet például html fájl is. Egy fájl beépítése esetén a PHP blokk a beépítés helyén megszakad, és a blokkon kívülre épül be a fájl tartalma. Például van három fájlunk: index.php, vars.php és menu.html a következő tartalommal:
vars.php:
<?php $refresh = "2010. április 7."; $email = "example@example.com"; ?>
menu.html:
<ul> <li><a href="index.php">Kezdőlap</a></li> <li><a href="cikkek.html">Cikkek</a></li> <li><a href="vendegkonyv.php">Vendégkönyv</a></li> </ul>
index.php:
<?php
...
include("vars.php");
...
?>
...
<body>
Utolsó frissítés: <?php print $refresh; ?><br />
<?php include("menu.html"); ?>
...
</body>
Pontosan azért kell a vars.php-be PHP blokk, mert az include() használata esetén a PHP blokkon kívülre kerül a beépített tartalom. Ugyanakkor ez teszi lehetővé, hogy html fájl tartalmát is be tudjuk építeni a HTML kódba. Az include() függvény az alábbi PHP kódot fogja eredményezni az index.php fájlban:
<?php ... ?> <?php $refresh = "2010. április 7."; $email = "example@example.com"; ?> <?php ... ?> ... <body> Utolsó frissítés: <?php print $refresh; ?><br /> <?php ?> <ul> <li><a href="index.php">Kezdőlap</a></li> <li><a href="cikkek.html">Cikkek</a></li> <li><a href="vendegkonyv.php">Vendégkönyv</a></li> </ul> <?php ?> ... </body>
A "kódot fogja eredményezni" kifejezés alatt nem azt értem, hogy a kód így fog kinézni, azzal nem történik semmi, csak az include() használata a fenti kóddal lesz egyenértékű. Az üres PHP blokkok a kód szempontjából olyanok, mintha ott sem lennének.
Ha más miatt nem is, az include() függvény használatáért valószínűleg érdemes használni a PHP-t az eddig készített nagyobb HTML oldalaidon (ha vannak ilyenek), mivel ezeknél általában vannak ismétlődő részek (mint például az itt bemutatott menü is). Ha például a menü-t egy külön html vagy php fájlba rakod, majd az egyes aloldalakon az include() használatával beépíted, sokkal egyszerűbb dolgod lesz, ha változtatni kell a menün, mivel ebben az esetben nem kell húsz fájlon elvégezni ugyanazt a módosítást, mivel a menü kódja csak egy helyen lesz tárolva.
Ha még nagyobbra duzzad az oldal, előfordulhat, hogy beépített fájlban is használunk include()-ot. Ebben az esetben (feltéve ha átlátjuk a hálózatot) csak az okozhat gondot, ha valamelyik beépített állomány függvények gyűjteménye. Mivel egy függvényt csak egyszer definiálhatunk, ezért egy ilyen állomány nem kerülhet be több példányban a PHP kódba, különben szép kis hibaüzenetek is be fognak kerülni. Ezt el lehet kerülni úgy, hogy az ilyen fájlok beépítéséhez az include_once() függvényt használjuk. Ez ugyanúgy működik, mint az include(), de csak akkor építi be az állományt ha még nem lett beépítve korábban ugyanezzel a függvénnyel. Persze ez a függvény csak önmaga ellen nyújt védelmet, ha később véletlenül az include()-dal akarnánk beépíteni az állományt, akkor újra beépülne, mivel az include() nem végez ilyen ellenőrzést.
Hasonló okok miatt sokszor előnyösebb, ha az ilyen állományok belsejében biztosítjuk, hogy ne épülhessenek be többször. A függvények definíciója a ciklusok és elégazások szempontjából megfelel egy utasításnak, így például megtehetjük, hogy a függvényeinket berakjuk egy if ágba:
<?php
if (...){
function fgv(){
...
}
// további hasznos vagy haszontalan függvények
}
?>
Ez nagyon szép, de mégis mit kellene írnunk a feltételbe? Mivel a PHP nem biztosít nyelvi elemet a beépítettség ellenőrzésére a beépítendő állományon belül, így például megtehetjük azt, hogy az if utasításon belül létrehozunk egy változót, a feltételben pedig a változó létezését ellenőrizzük. Ha korábban nem lett létrehozva a fájl, akkor az első beépítésnél a sok függvény beépül a kódba, a második alkalommal viszont már nem, mert a változó már létrejött az első beépítéskor.
<?php
if (!isset($functions)){
$functions = true;
// függvények
}
?>
Ez egészen addig működik, amíg nem vagyunk olyan okosak, hogy NULL értéket adjunk ugyanennek a változónak valahol máshol. Épp ezért, ezt konstansokkal érdemes megoldani, mert azoknak az értékét nem változtathatjuk meg, ha mégis megpróbálnánk, annak nem lenne semmilyen hatása. A konstansok esetén a létezést nem az isset(), hanem a defined() függvénnyel ellenőrizhetjük le, a visszatérési érték true, ha már definiáltuk a konstanst.
<?php
if (!defined("INCLUDED_FUNCTIONS")){
define("INCLUDED_FUNCTIONS", true);
// függvények
}
?>
A defined() függvény paramétereként a konstans nevét karakterlánc formában kell átadnunk, ugyanúgy, ahogy a define() függvénynek a létrehozáskor. Egyébként minden más esetben idézőjelek nélkül kell használni a konstans nevét. Itt egy logikai értéket adtam a konstansnak, de persze lehet bármi mást is. Érdemes minél hosszabb és rondább nevet választani, mert azzal csökkentjük az esélyét, hogy esetleg újra akarnánk definiálni.
Házi feladat
Mivel ez az "Alapok" rész utolsó leckéje, csak egy házi feladatot adok. A 4. lecke közepe táján van egy hosszabb PHP blokk, amellyel azt illusztráltam, hogy mennyi megjegyzést érdemes a PHP kódunkba beszúrkálni. Azt is megígértem, hogy ennek a leckének a végére eljutsz oda, hogy megértsd azt a programot. Remélem sikerült betartanom az ígéretet
Ugye nem is olyan bonyolult az a függvény?







