Hibakeresés

E könyv írásakor a PHP 4 semmilyen hibakeresõ eszközt nem tartalmazott.
A fejlesztõk ígéretet tettek hibakeresõ szolgáltatások beépítésére, például hogy
a verem tartalmát nyomon követhessük, ezért elképzelhetõ, hogy mire e könyv az
Olvasó kezébe kerül, a legfrissebb kiadás már tartalmaz valamilyen fejlettebb hibakeres
õ eszközt. Ebben a fejezetben a kódban rejlõ hibák felderítésének néhány
egyszerû módját mutatjuk be.
Az órában a következõ témákkal foglalkozunk:
• A PHP beállításainak lekérdezése
• A PHP által automatikusan elérhetõvé tett változók
• Hibaüzenetek kiírása naplófájlba
• Az adatok nyomon követése a programban
• A gyakori hibák felfedezése
• Információk a PHP-rõl és adott programokról
Ha egy program nem mûködik megfelelõen, érdemes elõször is a PHP beállításait
megvizsgálnunk. Ezután jöhetnek a PHP által létrehozott és a saját változók, és
ha még mindig nem találjuk a hibát, akkor megvizsgálhatjuk a forráskódot
egy olyan eszközzel, amely színkiemeléssel jelzi a nyelvtani elemeket – így hamar
rábukkanhatunk a problémás részre. Ebben a részben két módszert is megvizsgá-
lunk arra, hogyan szerezhetünk információkat a használt PHP-értelmezõrõl és
magáról a futó programról.
A phpinfo()
A phpinfo() függvény az egyik leghasznosabb hibakeresõ eszköz: részletes
információkkal szolgál magáról a PHP-rõl, a kiszolgálói környezetrõl és a futó
program változóiról. A függvénynek nem kell átadnunk semmilyen paramétert és
csak egy logikai értéket ad vissza, viszont egy csinos HTML oldalt küld a böngé-
szõnek. A phpinfo() kimenetét a 22.1. ábrán láthatjuk.
Az oldal tetején a használt PHP-változatról, a webkiszolgáló típusáról, a rendszerr
õl és a szerzõkrõl találunk információkat. A következõ táblázat részletezi a PHP
beállításait – ezeket a php.ini fájlban módosíthatjuk. Tegyük fel például, hogy
van egy "felhasznalo" nevû ûrlapmezõnk, de a programban valamilyen okból
nem jön létre a $felhasznalo változó. Vessünk egy pillantást a következõ beáll
ításokra:
track_vars On
register_globals Off
410 22. óra
22.1. ábra
PHP információk
megjelenítése
Már meg is találtuk a probléma forrását. A track_vars hatására a GET változók
a $HTTP_GET_VARS[] tömbben tárolódnak, a POST változók
a $HTTP_POST_VARS[] tömbben, míg a sütik a $HTTP_COOKIE_VARS[]
tömbben. Ez eddig rendben is van, a register_globals kikapcsolása azonban
azt jelenti, hogy a változók nem jönnek létre globális PHP változók formájában.
Alapállapotban mindkét lehetõség engedélyezett. Ebben az esetben két lehetõsé-
günk van. Keressük meg a register_globals bejegyzést a php.ini fájlban
és változtassuk On-ra. Nem tudjuk, merre keressük a php.ini fájlt? Nos,
a phpinfo() táblázataiban errõl is kaphatunk információt. A másik lehetõsé-
günk, hogy a "felhasznalo" mezõ tartalmára a program ne $felhasznalok
ént, hanem $HTTP_POST_VARS["felhasznalo"]-ként hivatkozzunk.
Egy olyan táblát is találnunk kell, amely a felhasználói munkamenetek kezelésére
vonatkozó beállításokat tartalmazza. Ha ez hiányzik, akkor a PHP-változatunkba
nem fordítottuk bele a munkamenetek kezelésének támogatását. A táblázatban
hasznos információkat találunk a munkamenetek kezelését megvalósító kód hibakeres
éséhez. Tegyük fel például, hogy olyan munkameneteket szeretnénk létrehozni,
amelyek bizonyos ideig fennmaradnak. Ha a munkamenet elvész, amikor
a felhasználó bezárja a böngészõ ablakát, és a phpinfo() a következõ beállítást
mutatja:
session.cookie_lifetime 0
már meg is találtuk a probléma forrását. A session.cookie_lifetime értéket
kell átállítanunk a php.ini fájlban, annak megfelelõen, hogy hány másodpercig
szeretnénk fenntartani a munkameneteket.
Ha a php.ini állomány a következõ sort tartalmazza:
session.use_cookies 0
a sütik nem engedélyezettek a munkamenetek kezelése során. Ebben az esetben
az azonosítás során a lekérdezõ karakterláncra kell hagyatkoznunk vagy módosí-
tanunk kell a beállítást a php.ini-ben.
A phpinfo() a webkiszolgálóról is rengeteg hasznos információval szolgál,
különösen akkor, ha Apache fut a gépünkön. Láthatjuk például a programmal
kapcsolatban forgalmazott összes kérés- és válaszfejlécet, illetve a kiszolgáló
környezeti változóit is (például HTTP_REFERER).
Ha a PHP-t adatbázis-támogatással fordítottuk, az erre vonatkozó beállításokat is
láthatjuk, például az alapértelmezett felhasználót, IP címet és kaput.
Hibakeresés 411
22
Az egyik legfontosabb információforrásunk lehet az a tábla, amelyben a PHP által
létrehozott globális változók vannak felsorolva az értékeikkel együtt. Lássunk erre
egy példát. A 22.1. példa egy egyszerû programot tartalmaz, amely létrehoz egy
HTML ûrlapot és beállít egy sütit.
22.1. program A phpinfo() függvény kipróbálása
1: 2: setcookie( "azonosito", "2344353463433",
time()+3600, "/" );
3: ?>
4:
5:
6: 22.1. program A phpinfo() függvény<br />kipróbálása
7:
8:
9:

"
METHOD="get"">
10:
11:

12:
18:

19:
20:

21:


22:

23:


24: 25: phpinfo();
26: ?>
27:
28:
Ha a „Lássuk!” gombra kattintunk, a program megkapja a felhasználó által megadott
adatokat és a süti is beállítódik. Ha meghívjuk a phpinfo() függvényt,
látni fogjuk ezeket a változókat – a kimenet lényeges részét a 22.2. ábrán láthatjuk.
412 22. óra
Látható, hogy a süti és a $HTTP_GET_VARS változó elérhetõ. Az ûrlap tartalmazott
egy olyan listát is, amelybõl több elemet is kiválaszthattunk – a változók között
a teljes tömb megjelenik.
Nagyobb lélegzetû feladatoknál gyakran gondot okoz az ûrlapváltozók és a sütik
nyomon követése, ilyenkor a phpinfo() felbecsülhetetlen segítséget nyújthat.
A forráskód megjelenítése színkiemeléssel
Ha nem találjuk meg a probléma forrását a phpinfo() függvény segítségével,
talán nem is a beállításokkal van baj. Jó ötlet lehet egy újabb pillantást vetni
a forráskódra. A PHP segítségével megtekinthetjük a program forráskódját,
ráadásul a kulcsszavakat, a karakterláncokat, a megjegyzéseket és a HTML kódot
színkiemeléssel is megjeleníthetjük.
Ha Apache kiszolgálót használunk, a beállítófájlhoz (többnyire httpd.conf) kell
hozzáadnunk a következõ sort:
AddType application/x-httpd-php-source .phps
Ezután minden .phps kiterjesztésû fájl színkiemeléssel fog megjelenni a böngé-
szõablakban. Ha nincs jogunk megváltoztatni a kiszolgáló beállítóállományát,
használjuk a show_source() függvényt, amely a paraméterül megadott fájlt
színkiemeléssel jeleníti meg a böngészõablakban.
Hibakeresés 413
22
22.2. ábra
Globális változók
elérése
A 22.2. példaprogram segítségével megtekinthetjük programjaink forráskódját.
22.2. program Dokumentum forrásának megjelenítése
1:
2:
3: 22.2. program Dokumentum forrásának<br />megjelenítése
4:
5:
6:
"
method="get">
7: Kérem a fájl nevét:
8:
9:



10: 11: if ( isset( $file ) )
12: show_source( $file ) or print "nem lehet
megnyitni a következõ fájlt: \"$file\"";
13: ?>
14:
15:
A 22.3. ábra a 22.2. példaprogramot mutatja mûködés közben.
Miért hasznos ez a lehetõség? Hiszen megnézhetnénk a kódot megszokott szövegszerkeszt
õnkkel is. A legnagyobb elõny a színkiemelésben rejlik. Igen könnyû
észrevenni például az elgépeléseket, hiszen ezeket nem kulcsszóként értelmezi
a megjelenítõ, ezért más színnel jelöli.
414 22. óra
22.3. ábra
Színkiemelés
használata
Egy másik gyakori probléma, hogy elég nehéz nyomon követni egy félig nyitott
idézõjel-párt. Mivel a PHP az idézõjel utáni szöveget karakterláncként értelmezi,
gyakran rossz helyen jelzi a hibát. Az idézõjelben lévõ karakterláncok szintén más
színnel jelöltek, így ez a típusú hiba nagyon könnyen észrevehetõ.
A 22.1. táblázat a színkiemelések jelentését tartalmazza.
22.1. táblázat Színkiemelések
php.ini bejegyzés Alapértel- Kód Jelentés
mezett szín
highlight.string Vörös #DD0000 Idézõjelek és
karakterláncok
highlight.comment Narancs #FF8000 PHP megjegyzések
highlight.keyword Zöld #007700 Mûveletjelek, nyelvi
elemek és a legtöbb
beépített függvény
highlight.default Kék #0000BB Minden egyéb PHP kód
highlight.html Fekete #000000 HTML kód
PHP hibaüzenetek
Miközben e könyv segítségével elsajátítottuk a PHP programozás alapjait, bizonyára
elõfordult, hogy hibaüzeneteket kaptunk a várt eredmény helyett. Például elfelejtett
ünk zárójelbe tenni egy kifejezést vagy elgépeltük egy függvény nevét. A hibaüzenetek
nagyon fontosak a hibakeresés során. Állítsuk a php.ini fájlban
a display_errors bejegyzést "On"-ra, ezzel biztosíthatjuk, hogy a PHP elküldje
a hibaüzeneteket a böngészõnek. Ne feledjük, hogy a phpinfo() függvény segíts
égével megnézhetjük, hogy be van-e kapcsolva ez a lehetõség.
Miután meggyõzõdtünk arról, hogy programunk tudatni fogja velünk az esetleges
hibákat, meg kell adnunk, hogy mennyire legyenek „szigorúak” az üzenetek.
Ha be akarunk állítani egy alapértelmezett szintet, rendeljünk a php.ini fájlban
az error_reporting bejegyzéshez egy számot. Szerencsére nem kell fejben
Hibakeresés 415
22
Ne tegyük ezt a programot elérhetõvé webhelyünkön, mert így
bárki belenézhet forrásainkba. Csak fejlesztéskor használjuk ezt
a kódot!
tartanunk az összes számot, mivel rendelkezésünkre állnak azok az állandók,
amelyeket a hibakezelés szintjének beállításához használhatunk. A különbözõ
értékeket a 22.2. táblázat tartalmazza.
22.2. táblázat Hibakezelési szintek
Állandó Név Leírás Mi történik?
E_ALL Mind Mindenféle hiba Függ a hiba típusától
E_ERROR Hibák Végzetes hibák Felhasználó értesítése és
(például memória- a program futásának
kiosztási problémák) megállítása
E_WARNING Figyelmeztetések Nem végzetes hibák Értesíti a felhasználót,
(például nem szabá- de nem szakítja meg
lyos paraméterátadás) a program futását
E_PARSE Értelmezõ hiba Az értelmezõ nem Felhasználó értesítése és
érti az utasítást a program futásának
megállítása
E_NOTICE Megjegyzések Lehetséges problé- Értesíti a felhasználót és
maforrás (például folytatja a program
egy kezdeti értékkel futtatását
el nem látott változó)
E_CORE_ERROR Belsõ hiba az értel- Az értelmezõ indítása- Megszakítja
mezõ indításakor kor fellépõ végzetes az értelmezõ indítását
hibák
E_CORE_WARNING Figyelmeztetõ Az értelmezõ indítása- Értesíti a felhasználót és
üzenet az értel- kor fellépõ nem folytatja a program
mezõ indításakor végzetes hibák futtatását
Ezekkel a beállításokkal nem változtathatjuk meg, mi történjen a hiba felbukkaná-
sakor, csak abba van beleszólásunk, hogy a hibaüzenetet el akarjuk-e küldeni
a böngészõnek vagy sem.
Természetesen egyszerre több hibakezelési szintet is engedélyezhetünk, ekkor
az egyes szinteket a VAGY (|) jellel elválasztva kell megadnunk. A következõ sor
például engedélyezi a hibaüzenetek és a figyelmeztetések megjelenítését is:
error_reporting = E_ERROR|E_WARNING
416 22. óra
Ha a hibakezelést az összes hibatípusra ki akarjuk terjeszteni, használjuk az E_ALL
állandót. Mi a teendõ akkor, ha az összes típust engedélyezni szeretnénk, kivéve
egyet? A következõ sor éppen ezt valósítja meg:
error_reporting = E_ALL & ~E_NOTICE
Az értelmezõ a megjegyzéseken kívül minden felmerülõ üzenetet elküld
a böngészõnek.
Az E_ERROR|E_WARNING és az E_ALL&~E_NOTICE tulajdonképpen kettes
számrendszerbeli aritmetikai mûveletek, melyek eredménye egy új hibakezelési
szintet megadó szám. A kettes számrendszerbeli aritmetikával ebben a könyvben
nem foglalkozunk, de a módszer ettõl még remélhetõleg érthetõ marad.
A php.ini beállítását az error_reporting() függvénnyel bírálhatjuk felül,
melynek bemenõ paramétere a hibakezelési szintet megadó egész szám, visszaté-
rési értéke pedig a megelõzõ hibakezelési beállítás. Természetesen ennél a függv
énynél is használhatjuk az elõzõekben megismert állandókat. Lássunk egy példát
egy olyan esetre, ahol a hibakezelési szint módosítása a segítségünkre lehet.
Lássuk, észrevesszük-e a szándékolt hibát a 22.3. programban.
22.3. program Egy szándékos hiba
1: 2: error_reporting( E_ERROR|E_WARNING|E_PARSE );
3: $flag = 45;
4: if ( $flg == 45 ) {
5: print "Tudom, hogy a \$flag változó értéke 45";
6: } else {
7: print "Tudom, hogy a \$flag változó értéke NEM 45";
8: };
9: ?>
Mint látható, a $flag változó értékét akarjuk vizsgálni, de elgépeltük. Nincs végzetes
hiba a programban, így minden további nélkül lefut és
az E_ERROR|E_WARNING|E_PARSE hibakezelési beállítás mellett még csak üzenetet
sem küld a böngészõnek. A kód bekerül a programba és a lehetõ legrosszabb
pillanatban mûködésbe lép. Ha azonban az error_reporting() függvénynek
az E_ERROR|E_WARNING|E_PARSE|E_NOTICE értéket adnánk át (ez magában
foglalja a megjegyzések elküldését is), a program a következõ kimenetet küldené:
Hibakeresés 417
22
Warning: Undefined variable: flg in /home/httpd/htdocs/
å peldak/22.3.program.php on line 4
Tudom, hogy a $flag változó értéke NEM 45
Azaz:
Figyelem: Nem meghatározott változó: flg a /home/httpd/htdocs/
å peldak/22.3.program.php fájlban a 4. sorban
Tudom, hogy a $flag változó értéke NEM 45
Az üzenetbõl nem csak az derül ki számunkra, hogy valami nincs rendben,
de még a problémás sor számát is megtudtuk. Ugyanezt a hatást úgy is elérhetjük,
ha az error_reporting() függvénynek az E_ALL állandót adjuk át paramé-
terként, ennek azonban lehetnek nem kívánt mellékhatásai is. Elképzelhetõ az is,
hogy szándékosan alkalmazunk nem meghatározott változókat. Vegyük például
a következõ kódrészletet:

Itt azt használjuk ki, hogy ha egy nem meghatározott változó értékét íratjuk ki,
akkor annak hasonló a hatása ahhoz, mintha egy üres karakterláncot jelenítenénk
meg (tulajdonképpen semmilyen hatása nincs). A "felhasznalo" mezõ
egy elõzõleg elküldött értéket vagy semmit sem tartalmaz. Ha a megjegyzések
elküldését is engedélyeztük, hibaüzenetet kapunk.
Hibaüzenetek kiírása naplófájlba
Azok a hibák, amelyekre eddig vadásztunk, nagyobb részben azonnali, fejlesztés
közben keletkezõ hibák voltak. Vannak azonban olyan problémák is, amelyek
késõbb jönnek elõ, például azért, mert megváltozik a futtató környezet. Tegyük fel
például, hogy szükségünk van egy programra, amely a felhasználó által kitöltött
ûrlap adatait írja fájlba. Elkészítjük a programot, kipróbáljuk, mérjük a teljesítm
ényét éles körülmények között, majd magára hagyjuk, hogy végezze a feladatát.
Néhány héttel késõbb azonban véletlenül töröljük azt a könyvtárat, amely az adott
fájlt tartalmazza.
A PHP error_log() függvénye pontosan az ilyen esetekre kifejlesztett hibakeres
õ eszköz. Ez egy beépített függvény, amellyel a kiszolgáló naplófájljába vagy egy
általunk megadott fájlba naplózhatjuk a felmerülõ hibákat. Az error_log()
függvénynek két bemenõ paramétere van: egy karakterlánc, amely a hiba szövegét
tartalmazza és egy egész szám, amely a hiba típusát írja le. A hiba típusától függõ-
en egy további paramétert is meg kell adnunk az error_log() függvénynek:
egy elérési utat vagy egy e-mail címet.
418 22. óra
A 22.3. táblázat az elérhetõ hibatípusokat sorolja fel.
22.3. táblázat Az error_log() függvény hibatípusai
Érték Leírás
0 A hibaüzenetet a php.ini fájl error_log bejegyzésénél
megadott fájlba kell kiírni.
1 A hibaüzenetet a harmadik paraméterben megadott
e-mail címre kell küldeni.
3 A hibaüzenetet a harmadik paraméterben megadott fájlba
kell kiírni.
Ha hibanaplózást szeretnénk, adjunk meg egy naplófájlt a php.ini error_log
bejegyzésénél. Természetesen a phpinfo() függvénnyel megnézhetjük, van-e
már ilyen beállítás a php.ini fájlban. Ha nincs, adjuk hozzá a fájlhoz például
a következõ bejegyzést:
error_log = /home/httpd/logs/php_errors
Ha NT vagy Unix operációs rendszert használunk, a "syslog" karakterláncot is
hozzárendelhetjük az error_log bejegyzéshez. Ekkor a 0-ás hibatípussal
meghívott error_log() hibaüzenetek a rendszernaplóba (Unix), illetve
az eseménynaplóba (NT) kerülnek. A következõ kódrészlet egy hibaüzenetet
hoz létre, ha nem tudunk megnyitni egy fájlt:
fopen( "./fontos.txt", "a" )
or error_log( __FILE__.", ".__LINE__.". sor:
å Nem lehet megnyitni a következõ fájlt: ./fontos.txt", 0 );
A hibaüzenet a __FILE__ és __LINE__ állandókat használja, amelyek az éppen
futó program elérési útját, illetve az aktuális sor számát tartalmazzák. A 0-ás hibatí-
pussal azt adjuk meg, hogy a hibaüzenet a php.ini fájlban megadott helyre kerülj
ön. Ezek alapján valami ilyesmi bejegyzés kerül a naplófájlba:
/home/httpd/htdocs/proba5.php, 4. sor:
å Nem lehet megnyitni a következõ fájlt: ./fontos.txt
Ha a hibaüzenetet adott fájlba akarjuk kiküldeni, használjuk a 3-as hibatípus
paramétert:
Hibakeresés 419
22
if ( ! $megvan = mysql_connect( "localhost", "jozsi",
"valami" ) )
{
error_log( date("d/m/Y H I")." Nem lehet csatlakozni
az adatbázishoz",
3, "dbhiba.txt" );
return false;
}
Ha 3-as típusú hibaüzenetet hozunk létre, egy harmadik paraméterben azt is meg
kell adnunk az error_log() függvénynek, hogy hová kerüljön a hibaüzenet.
Az error_log() függvénynek azt is megadhatjuk, hogy a hibaüzenetet egy
e-mail címre postázza. Ehhez az 1-es típuskódot kell használnunk:
if ( ! file_exists( "kritikus.txt" ) )
or error_log( "Ó, nem! kritikus.txt-nek vége van!",
å 1, "veszeset@kritikus.hu" );
Ha 1-es típusú hibaüzenetet küldünk, az error_log() harmadik paraméterében
meg kell adnunk az e-mail címet is.
A hibaüzenet elfogása
Ha hibaüzeneteket írunk egy fájlba vagy elektronikus levélben küldjük el azokat,
hasznos lehet, ha hozzáférünk a PHP által elõállított hibaüzenethez.
Ehhez a php.ini fájlban a track_errors bejegyzést "On"-ra kell állítanunk –
ennek hatására a legutolsó PHP hibaüzenet bekerül a $php_errormsg változóba
(hasonlóan a Perl $! változójához).
A $php_errormsg változó felhasználásával a hibaüzeneteket és naplóbejegyz
éseket beszédesebbé tehetjük.
A következõ kódrészlet által létrehozott hibaüzenet már sokkal használhatóbb,
mint az elõzõek:
fopen( "./fontos.txt", "a" )
or error_log( __FILE__.", ".__LINE__.". sor:
".$php_errormsg, 0 );
Az üzenet így fog festeni:
/home/httpd/htdocs/proba.php, 21. sor:
fopen("./fontos.txt","a") - Permission denied
420 22. óra
Kézi hibakeresés
Mindig nagyon nehéz azonban az olyan hibák kijavítása, amelyek nem váltanak ki
hibaüzenetet.
A hibakeresés egyik kézenfekvõ módja, ha megtûzdeljük a kódunkat print utasí-
tásokkal és kiíratjuk a fontosabb változók értékét. A futás során a változók ugyanis
gyakran nem várt értékeket vesznek fel
Egy jellemzõ nyomkövetõ sor:
print "

\$valtozo: $valtozo

";
Ez egy gyors próba, amit beszúrhatunk a programba, a $valtozo értékének
ellenõrzésére.
Természetesen a fent alkalmazott módszer nem kötelezõ érvényû – mindenki
kialakíthatja a saját módszerét, például:
print "

".__LINE__.": \$teszt értéke: $teszt

";
Talán a legkényelmesebb módszer, ha írunk egy függvényt a változók értékének
nyomon követésére és az include() használatával elérhetõvé tesszük a fejleszt
ési szakaszban. A 22.4. példa egy olyan függvényt tartalmaz, amely lehetõvé teszi
a fejlesztõ által megadott formátumú nyomkövetési üzenetek megjelenítését.
22.4. program Formázott nyomkövetési üzenetek megjelenítése
1: 2: function debug( $sor, $uzenet)
3: {
4: static $hivasok = 1;
5: print "


\n";
6: print "DEBUG $hivasok: $sor. sor: $uzenet
";
7: $argumentumok = func_get_args();
8: if ( count( $argumentumok ) % 2 )
9: print "Páratlan számú paraméter!
";
10: else
11: {
12: for ( $x=2; $x< count($argumentumok); $x += 2 )
13: {
14: print "   \$$argumentumok[$x]: "
.$argumentumok[$x+1];
Hibakeresés 421
22
22.4. program (folytatás)
15: print " .... (".gettype(
$argumentumok[$x+1] ).")
\n";
16: }
17: }
18: print "

\n";
19: $hivasok++;
20: }
21: $proba = 55;
22: debug( __LINE__, "Elsõ üzenet:", "proba", $proba );
23: $teszt = 66;
24: $proba2 = $proba/2;
25: debug( __LINE__, "Második üzenet", "proba", $proba,
"proba2", $proba2 );
26: ?>
A debug() függvénynek egy sorszámot, egy üzenetet, illetve tetszõleges számú
név–érték párt adhatunk át. A sor számát és az üzenetet kiírni a feladat könnyebbik
része. Ezután ki kell használnunk a PHP 4 azon tulajdonságát, hogy egy függvényt
változó számú paraméterrel is meghívhatunk. A func_get_args() által visszaadott
tömb függvényünk összes paraméterét tartalmazza – ezeket a változókat
töltjük be az $argumentumok tömbbe. Mivel név–érték párokat várunk, hibaüzenetet
kell adnunk, ha páratlan számú elem érkezik a tömbben. Egyébként végigl
épkedünk a tömb összes elemén (a harmadikkal kezdve) és kiíratjuk az összes
párt a változó adattípusával együtt. A 22.4. ábra a 22.4. program kimenetét mutatja.
422 22. óra
22.4. ábra
A debug() függvény
használata
Gyakori hibák
Mindannyian követünk el hibákat, különösen akkor, ha vészesen közeledik
a leadási határidõ. Vannak olyan csapdák, amelyekbe elõbb-utóbb minden programoz
ó beleesik.
Észrevesszük a hibát a következõ kódrészletben?
$valtozo=0;
while ( $valtozo < 42 );
{
print "$valtozo
";
$valtozo++;
}
A kapkodás sokszor vezet hibához – például az utasítássort jelölõ pontosvesszõt
gyakran kitesszük olyan helyeken is, ahol nem kellene. Így kerülhetett a fenti
while kifejezés mögé is pontosvesszõ, ami azt jelzi az értelmezõnek, hogy
a ciklus törzse üres – a $valtozo értéke soha nem fog nõni, ezért a program
végtelen ciklusba kerül.
Lássunk még egy példát:
$ertek = 1;
while ( $ertek != 50 )
{
print $ertek;
$ertek+=2;
}
Az elöltesztelõ ismétléses vezérlési szerkezet ciklustörzsének végrehajtása a záró-
jelben található kifejezés logikai értékétõl függ. A fenti példában ez a kifejezés
csak akkor lesz hamis, ha az $ertek változó értéke 50. Vagyis a ciklustörzs addig
ismétlõdik, amíg az $ertek értéke nem 50. Csakhogy ez soha nem fog bekövetkezni,
mivel a változó értéke 1-rõl indul és minden lépésben kettõvel növekszik –
vagyis csak páratlan értékeket vesz fel. Ismét sikerült végtelen ciklusba ejtenünk
a PHP-t.
A következõ kódrészletben rejlõ hiba elég alattomos:
if ( $proba = 4 )
{
print "

A \$proba értéke 4

\n";
}
Hibakeresés 423
22
A végrehajtást vezérlõ logikai kifejezésben nyilvánvalóan ellenõrizni akartuk
a $proba változó értékét. A kód azonban ehelyett 4-et rendel a $proba-hoz.
Mivel a hozzárendelés mint kifejezés értéke a jobb oldali operandussal egyenlõ
(jelen esetben 4-gyel), a logikai kifejezés értéke a $proba-tól függetlenül mindig
igaz lesz. Ezt a típusú hibát azért nehéz felfedezni, mert semmilyen üzenetet nem
hoz létre, a program egyszerûen nem úgy fog mûködni, ahogyan azt elvárjuk.
A karakterláncok kezelése során szintén elkövethetünk típushibákat. Az alábbi
elég gyakori:
$datum = "A mai dátum: . date('d/m/Y H I’);
print $datum;
Mivel nem zártuk le az idézõjelet, az értelmezõnek fogalma sincs, hol végzõdik
a karakterlánc. Ez szinte mindig hibajelzéssel jár, de nehézkes visszakeresni, mivel
gyakran rossz sorszámot kapunk. A zárójelpárok hibás kezelése szintén hasonló
jelenséghez vezet.
A következõ hibát viszont elég könnyû megtalálni:
print "Ön a $tartomany-ról "$felhasznalo"-kent
å jelentkezett be";
Ha idézõjelet akarunk kiíratni, jeleznünk kell az értelmezõnek, hogy itt nem különleges
karakterként kell kezelnie. Az elõbbi kódrészlet a következõképpen fest
helyesen:
print "Ön a $tartomany-ról \"$felhasznalo\"-kent
å jelentkezett be";
Összefoglalva, ebben a részben a következõ gyakori hibatípusokkal foglalkoztunk:
• Üres ciklustörzs létrehozása hibásan alkalmazott pontosvesszõvel.
• Végtelen ciklus létrehozása hibás vezérlõfeltétellel.
• Hozzárendelés használata az „egyenlõ” logikai mûveletjel helyett.
• Levédetlen idézõjelek használata miatt elcsúszott karakterlánc-határok.
424 22. óra
Összefoglalás
A fejlesztés talán egyik leghálátlanabb része a hibakeresés. A megfelelõ módszerekkel
azonban megkönnyíthetjük az életünket.
Ebben az órában tanultunk arról, hogy a phpinfo() függvény segítségével
hogyan nyerhetünk információkat a rendszer beállításairól és a környezeti változ
ókról. Az error_log() függvénnyel hibaüzeneteket írtunk ki fájlba és küldt
ünk el elektronikus levélben. Tanultunk a kézi hibakeresésrõl a fontosabb változ
ók értékének kiíratásával és írtunk egy függvényt a feladat megkönnyítésére.
Ha ismerjük az adatokat, amelyekkel programunk dolgozik, viszonylag könnyen
és gyorsan megtalálhatjuk a hibákat. Végül megnéztünk néhány olyan típushibát,
amelyek még a tapasztaltabb programozók életét is megkeserítik.
Kérdések és válaszok
Létezik módszer, amellyel csökkenthetjük a kódba kerülõ hibákat?
Legyünk szemfülesek! Tulajdonképpen szinte lehetetlen egy olyan nagyobb lélegzet
û programot létrehozni, amely elsõre tökéletesen mûködik. Használjunk modul
áris tervezést, hogy gyorsan elkülöníthessük a hibát tartalmazó kódrészletet. Olyan
gyakran ellenõrizzük a kódot, amilyen gyakran csak lehetséges. Rossz megközelí-
tés, ha megírjuk a programot, elindítjuk, azután várjuk, mi történik. Oldjunk meg
egy részfeladatot (lehetõleg függvények formájában), majd próbáljuk ki az elké-
szült kódot. Ha tökéletesen mûködik, mehetünk a következõ részfeladatra. Próbáljunk
„bolondbiztos” kódot készíteni és ellenõrizzük mûködését szélsõséges körülm
ények között. Ha az egyik leglényegesebb lépés például az adatok kiírása egy
megadott fájlba, nézzük meg, mi történik, ha a fájl hiányzik.
Mûhely
A mûhelyben kvízkérdések találhatók, melyek segítenek megszilárdítani az órában
szerzett tudást. A válaszokat az A függelékben helyeztük el.
Kvíz
1. Melyik függvénnyel kaphatunk hasznos információkat a PHP-rõl és a rendszer
ünkrõl?
2. Melyik függvénnyel jeleníthetjük meg a színekkel kiemelt forráskódot
a böngészõablakban?
Hibakeresés 425
22
3. Melyik php.ini bejegyzéssel szabályozhatjuk a hibaüzenetek kijelzésének
szintjét?
4. Melyik függvénnyel bírálhatjuk felül ezt a beállítást?
5. Melyik függvénnyel naplózhatjuk a hibákat?
6. Melyik beépített változó tartalmazza a hibaüzenetet, ha a track_errors
bejegyzés engedélyezett a php.ini fájlban?
Feladatok
1. Vizsgáljuk meg eddig elkészült programjaink kódját és felépítését az ebben
az órában tanult módszerek segítségével.