Hibakeresés PHP-ban

Tartalom

Bevezető
Elég gyakori, hogy alapvető hibákat nem találnak meg kezdő, vagy sokszor haladó programozók sem. Ehhez próbálok segítséget nyújtani pár hasznos tanáccsal. Érdemes megfogadni őket. Leginkább PHP-ról fogok szólni a cikkben, de megpróbálok általánosságban is megemlíteni pár dolgot.

Alapvetően kétféle hibát különböztethetünk meg.

  1. Szintaktikai
    Ebben az esetben valószínűleg elírtunk valamit a programkódban, és egy olyan utasítás került a forrásba, ami nem értelmezhető az adott nyelven, vagy lehagytunk egy fontos elemet figyelmetlenségből. Például egy pontosvesszőt az utasítás végén, ha a programnyelv igényli. Ha szintaktikai hibát ejtünk, a program nem fordul le, illetve script nyelv esetén hibaüzenettel leáll értelmezéskor.

  2. Szemantikai
    Meglehet, hogy a kódunk szintaktikailag helyes, és látszólag minden a helyén van, de nem gondoltuk át kellőképpen, hogy mit is szeretnénk megvalósítani. Esetleg nem ismerjük kellőképpen a használt függvények működését, és rossz módszert alkalmazunk, aminek következtében a program bár helyes, tényleg nem azt fogja „művelni” amit elvárnánk tőle.

Nos, egyik esetben sem a számítógépünket kell püfölni, vagy gondolkodás nélkül írni egy fórumra, és leírni, hogy „nem működik, segítsetek”. Első lépés, hogy gondolkodunk magunk, és utánajárunk, miben hibáztunk. Majd csak a második lépés lehet, hogy más segítségét is igénybe vesszük. Elvégre emberek vagyunk. Lehet, hogy nem tűnik fel valami akkor sem, ha szinte kiszúrja a szemünket.

Na de nézzük meg a lehetséges hibajelenségeket, és a hiba detektálásának módjait.

Szintaktikai hibák

Szintaktikai hibával kezdeném, mivel ezt a legegyszerűbb megtalálni. Mégis van, akik nem tudják értelmezni a kapott hibaüzenetet. Igen, kicsit nem árt tudni angolul, de nem feltétel. Kis erőfeszítéssel nyelvtudás nélkül is megérthetjük a számunkra kínai angol szöveget. Egy hasznos weboldal ehhez: http://webforditas.hu
De ezen kívül is van több a neten. Végig kell nézni a szavakat egyenként addig, amíg úgy tűnik, már érthető mire is „gondol” az a fránya hibaüzenet.

PHP esetén gyakori hibaüzenet:

Parse error: syntax error, unexpected T_VARIABLE in /media/sda6/dev/hibaker/syntax.php on line 6

Ha ilyen hibaüzenet fogad, biztos lehetsz benne, hogy szintaktikai hibát vétettél. Erre utal a „Syntax error” angol kifejezés is.
T_VARIABLE: Olyan helyen használtál változót, ahol nem lehetne. Most megmutatom mi is okozta ezt a hibaüzenetet.

<?php

$a=10;
$b=25

$osszeg = $a+$b;

?>

Na de most akkor mi itt a hiba? Feltételezem, ebben a pici példában mindenkinek feltűnt, hogy a $b=25 után nincs pontosvessző. De hát az a 4. sor, és nem a 6. Miért a 6. sorban jelez hibát? Talán tévedett az interpreter? A válasz nem! A PHP értelmezője soronként megy végig a forráskódon, és ott fog csak hibát jelezni, ahol olyan kódot talál, ami nem lehetne ott. Jelen példában pedig akár a 6. sorban is lehetne pontosvessző, ami lezárja a 4. sorban levő utasítást. Tehát jogosan nem jelzett előbb. Az értelmező azt nem tudja megmondani, hogy valami hiányzik, csak azt, hogy valami rossz helyen van. Ám ebből következtethetünk arra, hogy a jelzett sor előtt van a hiba, hisz a 6. sorban minden rendben.

Nézzünk egy másik kódot:

<?php

$a=10;
$b=25+;

$osszeg = $a+$b;
?>

Lemaradt a második operandus a 25 után, de a + jel ott maradt, vagy véletlenül került oda a + jel? Ezt az értelmező nem fogja tudni kitalálni, de a hibaüzenet:

Parse error: syntax error, unexpected ';' in /media/sda6/dev/hibaker/syntax.php on line 4

Jelzi, hogy itt most a pontosvessző van rossz helyen. Hogy miért? Mert a + jel minden gond nélkül állhat egy szám után, de egy plusz jel után nem állhat pontosvessző. Kivétel a $i++; Ám itt is egy második + jel van az első után, így ez helyes. Ebben a hibaüzenetben tehát még a sorszám is jó sort mutat, de ez nem feltétlenül van mindig így. Ettől nem kell megijedni, csak gondolkodni kell, és meg kell nézni az előző sorokat is. Megjegyzem, ugyanilyen hibát kaphatsz, ha nem zársz le egy megnyitott idézőjelet, vagy aposztrófot.

Lehet még blokk hiba is, amikor egy if, while, vagy egyéb blokk meg van nyitva, és nincs meg a kapcsos zárójel párja, ami lezárja. Ez gyakran előfordulhat hosszabb kódok esetén, amikor sok egymást követő nyitó és záró zárójel van. Ilyenkor például hasonló üzenet fogadhat:

Parse error: syntax error, unexpected $end in /media/sda6/dev/hibaker/syntax.php on line 11

Itt az $end szimbólum jelzi, hogy az értelmező eljutott a fájl legvégéig, és hiányol még onnan valamit. Valójában persze cseppet sem biztos, hogy a fájl végén van a hiba, de mivel az egyes blokkok akárhányszor egymásba ágyazhatóak, a fájl végéig nem veszi észre, hogy hiba van, hisz nem tudhatja, hogy nem a teljes további forrást akartuk abba a blokkba zárni. Ilyenkor végig kell nézni a zárójeleket. Célszerű már a szerkesztéskor gondolni erre, és behúzásokkal tagolni a forrást. Akkor könnyebben észrevehetők az efféle hibák. És most nézzük a kódot ami ezt a hibát okozta:

<?php

$a=10;
$b=25;

if ($a > 20) {
    $osszeg = $a+$b;

?>

Nem részletezném tovább a lehetséges hibákat, mert rengeteg féle lehet, és sose végeznék a listával. Oda kell figyelni.

Összefoglalva tehát az eddigieket:

  1. A syntax error szintaktikai hibára utal a forrásban.

  2. Az unexpected szó után található a hibás helyen levő karakter, vagy esetleg egy szimbólum, ami a hibás rész típusára utal.

  3. Ez után egy fájl elérési útja található, amiben a hiba található. Ez akkor hasznos, ha több, egymásra hivatkozó programról van szó, amikor nem feltétlenül a böngészőben látható fájlban van a hiba.

  4. Majd végül egy sorszám található. Ám ez nem feltétlenül a hibás sort adja meg, de támpontot ad, hogy merre keresgéljünk

Szintaktikai hibák kereséséhez szerezzünk be egy kódszínező forráskódszerkesztőt, vagy használjuk a php beépített kódszínezőjét: highlight_string(); illetve highlight_file(); függvények. Működésükről a http://php.net/manual oldalon található információ.

Bár a magyar nyelvű dokumentációt már megszüntették, azért még lehet találni korábbi dokumentációk magyar nyelvű lementett változataiból google-val.

Függvénylista: http://hu.php.net/manual/en/indexes.php

Szintaktikai hibák MySQL-ben

Némi szót azért érdemel ez a téma is, mivel PHP-ban gyakran van szükség MySQL adatbázisra. Nem biztos azonban az, hogy a hibás SQL kódról bármilyen információt kapsz, ha csak nem kéred ezt. Hibaüzenetet a mysql_error() függvény adja vissza. Ha egy PHP program rosszul működik, lehet hogy a lekérdezésben van a hiba. Ezért érdemes kiíratni a mysql_error() tartalmát is. Ha van valami hiba, akkor ez tartalmazza az okát. Vegyük a következő táblát:

CREATE TABLE`szamok2` (
  `id` int(11) NOT NULL auto_increment,
  `szoveg` varchar(50) collate latin1_general_ci NOT NULL,
  PRIMARY KEY  (`id`)
);

Erre a táblára pedig ezt a lekérdezést írtam:

<?php

mysql_connect('localhost','user','jelszo');
mysql_select_db('test');

$sql = "select * from szamok2 where azon=5";

$sor = mysql_fetch_assoc(mysql_query($sql));
print $sor['szoveg'];
?>

Itt van ugyan hibaüzenet, de nem mond semmi hasznosat, csak hogy a mysql_fetch_assoc hibás argumentumot kapott.

Warning: mysql_fetch_assoc(): supplied argument is not a valid MySQL result resource in /media/sda6/dev/hibaker/syntax.php on line 8

Ebből lehet következtetni arra hogy az SQL kérés volt hibás, de hogy megtudd mi volt a hiba, írd be a mysql_query() -t tartalmazo sor után: print mysql_error(); Ekkor már kiírja hogy:

Unknown column 'azon' in 'where clause'

Tehát ismeretlen mezőre próbáltam hivatkozni a where feltételben. Valóban, mert nincs azon mező, csak id.
Vannak olyan hibák, amikor a MySQL nem csak a hibáról tájékoztat, hanem arról, hogy az SQL kérés hányadik sorában volt a hiba. Hosszabb lekérdezéseknél viszont ha egy sorba írtuk a kódot, nem túl hasznos információ, hogy az egy soros kód első sorában van a hiba. Ilyenkor célszerű az SQL kódon belül is sortöréseket alkalmazni. Például

$sql = "select * from szamok2 where id=5 o id=6 or id=10";

Szerintem mindenki látja, hogy az egyik or feltétel helyett csak o betűt írtam. Ekkor jelez a MySQL, hogy:

You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'o id=6 or id=10' at line 1

Most pedig sortörésekkel:

$sql = "select * from szamok2
    where id=5
    o id=6
    or id=10"
;

És a hibaüzenet, amivel közelebb kerülhetünk a megoldáshoz:

You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'o id=6 or id=10' at line 3

Persze ebben a példában sorszám nélkül is megtalálható lett volna a hiba, de néha jól jön egy pontosabb hibajelentés. Ugyanezt a módszert természetesen PHP esetén is alkalmazhatjuk, és egy bonyolultabb, összetett PHP kódot akár az if feltételben, vagy függvény paraméterezésben sortörésekkel megtoldva hasznosabb hibaüzenethez juthatunk.

Foglalt szavak

Ahogy minden programnyelven, MySQL-ben is vannak foglalt szavak, és ha olyan nevet adsz egy mezőnek, ami foglalt szó, akkor is hibaüzenetet fogsz kapni. Tehát érdemes a mezőneveket visszaaposztrofok közé tenni. ( Alt Gr + 7 ). Fontos, hogy nem sima aposztrófok közé, mert az a stringeket jelenti.

Szemantikai hibák

Hogy mit is jelent ez a kifejezés, arról már írtam. De hogy lehet megtalálni egy hibát, ha valójában nincs is hiba, csak rosszul programoztuk le a problémát?

  1. Kiíratás

    Ha látszólag jó a program, de mégsem a megfelelő eredményt adja, próbáld meg behatárolni, hogy kb merrefelé téved. Írasd ki a változók értékeit egy print utasítással. Ha tudod, hogy a programnak mit kellene csinálnia, akkor fel fog tűnni, ha egy változó nem olyan értéket kap, amilyet kellene.

  2. Függvények tesztelése.

    Elképzelhető, hogy egy függvény, amit írtál, hibás. Néhány esetben jó eredményt ad, de van, amikor téved. Teszteld le egyenként minél több féle paraméterrel a függvényt, hogy jó eredményt ad-e. Lehet, hogy ha javítod azt az egy hibás függvényt, az összes többi, látszólag független hiba is megjavul.

  3. Megjegyzésbe zárás

    Néha csak egy sor, vagy rövid utasítás okozza a hibát. Bár a program működése szempontjából fontosnak tűnik, lehet az okoz végtelen ciklust, ami miatt a programunk lefagy. Ilyenkor segíthet, ha a gyanús sorokat egyenként // jelek után, vagy /* és */ jelek közé tesszük egy megjegyzésbe. Ha ekkor a program lefut, nem számít, hogy rossz eredményt ad, mert megvan a hiba, amit már tudunk javítani és az eredmény is jó lesz.

Gyakori hibák MySQL adatbázis kezeléssel kapcsolatban

Ha adatbázist használsz, oda kell figyelni arra, hogy a kötelező elemeket sose hagyd ki. Gondolok itt a fetch-elésre, amivel megkaphatjuk a tényleges adatot egy adatbázisból. Elsőre többnyire csak valamiféle erőforrás azonosítót kapunk, amit át kell adni MySQL-ben például a mysql_fetch_assoc -nak, vagy egyéb fetch-elő eljárásoknak, amiket most nem taglalnék, mert ez kívül esik a cikk keretein. Lényeg, hogy ha belekezdesz egy program írásába, tudd, mit akarsz, és akard tudni, hogy tudod azt megvalósítani. Ehhez tanulni kell, de megéri, mert rögtön más szemmel néznek rád a fórumokon is, ha látják, hogy tanulsz. Akkor már a kérdezés sem lesz szégyen.

Néhány szemantikai hiba:

<?php
$a=10;
if ($a = 10) {
    $b=$a;
} else $b=20;
?>

Gyakorlott programozó is eltéveszti néha feltétel ellenőrzést, és csak 1 egyenlőség jelet ír kettő helyett. Ekkor viszont a feltétel mindig igaz lesz, ha valamilyen pozitív számmal, vagy true -ra konvertálható értékkel töltjük fel a változót. Ha viszont $a=0 lett volna a feltételben, akkor mindig hamis lett volna, mert a nullát false -ra konvertálja a PHP. Olykor hasznos lehet a feltételben rögtön értéket is adni, de oda kell figyelni, hogy az volt-e a cél.

<?php
For ($i=1; $j<10; $i++) {
        //itt történik valami
}
?>

Ebben pedig rögtön két hiba is lehet. Amennyiben nem használtál előtte $j változót, egy notice szintű hibát generál, ami általában az alapértelmezett szerverbeállításokkal rejtett, de a kód elejére írva, hogy error_reporting(E_ALL); máris kijelzi a hibát, hogy olyan változót próbáltál használni, ami nem volt még deklarálva.
A másik hiba, hogy az $i változót növeli a ciklus, és a $j változónak az értékét figyeli, ami sosem változik, így végtelen ciklusba lép.

Ide sorolhatjuk még az eltérő szerverbeállítások okozta hibákat, ami „Az én programom pedig működött, de hibás a szerver!” gondolatot válthatja ki. Persze meglehet, hogy még igaz is, de többnyire nem ez a helyzet. Egy webszervert több szempont szerint lehet beállítani, ám a programozónak oda kell figyelni, hogy az adott szerver beállításai megfelelnek-e a programnak.

  • Telepítve van-e a szükséges modul
  • Egy adott szerver változó hogy van beállítva

Ennek felderítésében segítségedre lehet a phpinfo(); függvény, ami egy rendezett, HTML formátumú oldalt jelenít meg, benne az összes fontos információval, amit a szerver és a PHP beállításairól tudni kell. Van, ahol ez a függvény le van tiltva. Ekkor esetleg még a következő kódot lehet használni, ha nincs letiltva az ini_get_all():

<?php
print "<pre>";
print_r(ini_get_all());
print "</pre>";
?>

Ez is listázza a php.ini beállításait, csak nem olyan szép formában.
Az egyik leggyakoribb hiba, hogy a programozó egy konkrét szerverre kódol, nem véve figyelembe, hogy esetleg később a szerver át lesz állítva, vagy más szerverre kell költözni, és a POST, GET, SESSION, COOKIE változókat helytelenül használja. Itt azért meg kell jegyeznem, hogy a helytelen nem feltétlenül hibásat jelent. De nem árt előre gondolni arra az eshetőségre, hogy szükség lehet szervert váltani. Mutatok egy példát:

<?php
if (isset($nevem)) {
        print "Üdvözöllek".$nevem;
}
?>
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8" />
</head>

<body>
<form action="" method="post">
<input type="text" name="nevem" >
<input type="submit" value="köszönj!">
</form>

</body>
</html>

Kipróbálhatod a programot. Sajnos ebben az esetben elképzelhető, hogy a program udvariatlan lesz, és nem köszön. Mindezt azért, mert bár sok PHP-ról szóló könyv így mutatja be a példaprogramokat, ha a szerveren a php.ini -ben a register_globals nevű változó off -ra van állítva, a $nevem változónak nem lesz értéke. Ahhoz, hogy minden szerveren jól működjön a köszönő program, a következő képpen kell írni:

<?php
if (isset($_POST['nevem'])) {
    print "Üdvözöllek ".$_POST['nevem'];
}
?>
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8" />
</head>

<body>
<form action="" method="post">
<input type="text" name="nevem" >
<input type="submit" value="köszönj!">
</form>

</body>
</html>

Jegyezzük meg tehát, hogy ezeket a változókat a következő formában célszerű írni:
$nevem helyett $_POST['nevem'], vagy $_SESSION['nevem'] vagy $_GET['nevem'] vagy $_COOKIE['nevem'], vagy $_REQUEST['nevem']

Ha így teszel, bárhova is költözteted a programot, mindenhol működni fog valószínűleg.
Ebből viszont adódhat egy szintaktikai hiba is, ezért kicsit visszakanyarodnék ahhoz a témához.
Mint láthatod, a szögletes zárójelekben levő karakterláncot, ami a változó neve tulajdonképpen, aposztrófok közé tettem ( tehettem volna idézőjelek közé is ). Erre azért van szükség, mert ellenkező esetben a nevem csak egy definiálatlan konstans lenne, ami szintén egy notice szintű hibát adna, miközben stringgé konvertálja a PHP. Ám ha van egy nevem nevű konstans definiálva, máris működésképtelen lehet a program tőle. Van azonban olyan eset, amikor el kell hagyni az idézőjelet. Például akkor, ha a változót egy karakterláncon belül íratod ki idézőjelek között. Például, ha a fenti példában a köszönést így írtam volna:

print "Üdvözöllek $_POST['nevem']";

Az ilyen hibát adott volna:

Parse error: syntax error, unexpected T_ENCAPSED_AND_WHITESPACE, expecting T_STRING or T_VARIABLE or T_NUM_STRING in /media/sda6/dev/hibaker/syntax.php on line 3

Szép ugye? A gond az, hogy itt a nevem-ből nem lesz konstans, mivel az egész egy idézőjelben van, és azon belül mégegy idézőjelbe tettem a nevem stringet, ami hiba. 3 megoldás lehetséges. Mindenki döntse el, melyik tetszik neki.

  1. Ha stringen belül írok ki ilyen változókat, nem teszem ki az aposztrófot.
    print "Üdvözöllek $_POST[nevem]";

  2. A változót kapcsos zárójelek közé teszem
    print "Üdvözöllek {$_POST['nevem']}";

  3. A változót kiemelem a stringből, és előtte lezárom az idézőjelet, hozzáfűzöm a stringhez és újra nyitom az idézőjelet
    print "Üdvözöllek ".$_POST['nevem'];

PHP header használat

Még ami kimaradt, az a header-ek használata. Ezzel is sokaknak meggyűlik a baja. Ugyanis a php ki tud küldeni bizonyos fejléc információkat, mint hogy átirányítson egy másik oldalra, vagy elindítsa a munkameneteket, cookie-t helyezzen el a böngészőben stb stb. De ez a 3 a gyakoribb szerintem.

Viszont azt tudni érdemes, hogy ezek a műveletek nem történhetnek meg az után, hogy a tényleges kimenetre küldtünk tartalmat. Legyen az akár egy szóköz, vagy egy teljes weboldal.
Rossz példa 1:

<?php
print "Most átirányítalak!";
header("Location: valami.php");
?>

Most átirányítalak!
Warning: Cannot modify header information - headers already sent by (output started at /media/sda6/dev/hibaker/kimenet.php:2) in /media/sda6/dev/hibaker/kimenet.php on line 3

Rossz példa 2:

 <?php
header("Location: valami.php");
print "Hoppácska... kimenetet küldtél egy szóközzel is";
?>

Warning: Cannot modify header information - headers already sent by (output started at /media/sda6/dev/hibaker/kimenet.php:1) in /media/sda6/dev/hibaker/kimenet.php on line 2
Hoppácska... kimenetet küldtél egy szóközzel is

output started at jelzi, hol van a header küldés, hányadik sorban, melyik fájlban. in után pedig ott van hogy hol küldtük ki a kimenetet véletlenül.
Ha ezekhez hasonló hibaüzenetet kapsz, járj utána a hibaüzenetben jelölt soroknak, és ha nincs mód a header-ök áthelyezésére a kimenetek elé, használj kimenet pufferelést.
Nagyon egyszerű. Keresd meg azt a fájl, ahol a hiba jelentkezik. És tedd be a fájl leges legelejére, természetesen itt is még kimenet küldés előtt, hogy:

<?php
ob_start();
?>

Helyes példa 1:

<?php
header("Location: valami.php");
print "Ezt már tényleg nem látod!";
?>

Helyes példa 2:

<?php
ob_start();
?>
<html>
<head><title>Cím</title></head>
<body>
Ezt se fogod látni, ha átirányítok
</body>
</html>
<?php
header("Location: valami.php");
?>

Figyelem: Bár én csak a header() -t írtam példaként, ugyanígy viselkedik a setcookie(), session_start(), de még az ob_start() is. Ezért kell utóbbit is kimenet előtt megadni.

Nincs szóköz, nincs kimenet, mégis hibás!

Két lehetőség van. Vagy elnézted, és mégis küldtél kimenetet, vagy te is áldozatául estél a nagy "karakterkódolásos mumusnak". Ugyanis a fájlok, amikbe a kódokat írod, rendelkeznek egy karakterkódolással. Úgyanugy, ahogy megadhatod html-ben, a fájlt is átállíthatod UTF-8, ANSI illetve egyéb értékekre. Ha viszont windows rendszerben, jegyzettömben szerkeszted a fájlokat, illetve előfordulhat más szerkesztőnél is, ha UTF-8 ban mented el az állományt, bekerül néhány jelző karakter a fájl legelejére. Oda, ami elé már írni sem tudsz, és nem is minden szerkesztő mutatja meg hogy van ott valami, pedig van.
Megoldás: Gyorsan ( vagy lassan is akár :) ) változtasd meg UTF-8 -ról ANSI -ra a karakterkódolását a fájlnak.
jegyzettömb -> File -> Mentés másként -> és itt alul a lenyíló lista

Természetesen nem muszáj kódolást változtatnunk csak ezért. Megtehetjük, hogy keresünk egy olyan forráskódszerkesztőt, ami tud BOM nélkül menteni. Ez a bizonyos BOM az a néhány oda nem való karakter, ami a hibát okozza. Nodepad++ például már tud így is menteni. Illetve linux rendszereken nem kell aggódni emiatt a probléma miatt.

Nem hiba, de mégis. Avagy másik szerveren még működött

Többféle hibatípus is bele tartozik ebbe a kategóriába. Tulajdonképpen az előbb említett BOM karakter hibája is ide tartozik. Találkoztam már olyan esettel, hogy windows szerveren - Milyen meglepő... - jó volt a program, de linuxon már nem. Ez nem a linux hibája, gondolom, ha már a Microsoft használja a BOM -ot az alap notepad-jában erőszakos módon, akkor saját találmányait fel is ismeri.

Ezért tehát fontos, hogy ne csak aszerint kódoljunk, hogy valami működik-e aktuálisan a teszt tárhelyünkön, hanem tartsuk be a szükséges szabályokat. Törekedjünk a szép forráskódra, ami behúzásokkal megkönnyíti egy hiba megtalálását, vagy csak a kód megértését. Nem árt megjegyzéseket sem fűzni egyes kódrészletekhez.

A blokk zárójelek elhagyhatók ciklusnál, feltételnél, ha csak egy utasítást fog tartalmazni a blokk. Ennek ellenére tegyük csak ki azokat a zárójeleket a későbbi problémák elkerülése végett.

Az asszociatív tömb indexeket mindig tegyük idézőjelbe. Vagy kettős idézőjelbe, vagy aposztrófba.
$tomb[index]
helyett
$tomb['index']

Ide tartozik még a már szintén említett error_reporting(E_ALL); használata is.
HA ezt legalább teszteléskor használjuk, kiderülhetnek apróbb hibák, amik nem tűntek fel. A következő kódrészletet a forrás elejére beszúrva csak akkor jelennek meg a hibák, ha weblapot localhost -ról futtatjuk. Ha viszont IP címről, vagy normál domainről próbáljuk elérni, akkor minden hibaüzenetet letilt.

<?php
if ($_SERVER['HTTP_HOST'] == 'localhost') {
        error_reporting(E_ALL);
} else {
        error_reporting(0);
}
?>

Így elkerülhető, hogy olyan részleteket lássanak a látogatók egy hiba bekövetkezésekor, ami esetleg felhasználható egy támadáshoz.

Mindent megpróbáltam, de mégis muszáj kérdeznem tapasztaltabbaktól

Előfordulhat, hogy már tényleg mindent kipróbálunk, vagy legalábbis azt hisszük. Ha valaki úgy érzi, már nem tud mit tenni a hiba megtalálása érdekében, és egy fórumhoz fordul, hogy kérdezhessen, akkor a következőket kell szem előtt tartani:

  • Az eredeti cél megfogalmazása

    Ahhoz, hogy segíteni lehessen, tudni kell, hogy mit kellene tennie a programnak. Adott esetben két különböző program is helyes lehet, miközben az egyik nem azt teszi, amit elvárnánk. Viszont senki sem olvashat a kérdező gondolataiban, hogy mi volt az ő célja.

  • Hibajelenség pontos leírása

    Ha már tudja a segítőnk, hogy mit kellene a programnak művelnie, a következő, amire kíváncsi, hogy mit tesz ahelyett.

  • Hibaüzenetek

    Fontos az összes hibaüzenet idézése. Mert ha te nem is tudod a hibaüzeneteket értelmezni, egy hozzáértő könnyen lehet, hogy azonnal rávágja mi a probléma.

  • Forráskód

    Ha megmutatod a forráskódját a programnak, amiben a hiba előfordul, szintén megkönnyíted a segítséget.

  • Demo oldal

    Szükség lehet egy példa oldalra is, amin élőben látható a hiba.

  • Eddigi próbálkozások bemutatása

    Éppen elég hibát és problémát kell megoldaniuk a fórumozóknak. Mutasd meg nekik, hogy milyen módszerekkel próbáltad megoldania problémád.
    Egy részt azért, hogy lássák, tettél érte, és szívesebben segítsenek, más részt azért, hogy tudják, milyen módszereket nem kell már ajánlaniuk.


Bizonyára nem írtam le minden lehetséges hibát, de nagyjából hasonló lépéseket kell végrehajtani minden hiba keresésénél. Vannak programnyelvek, ahol lehet lépésenként végrehajtani a programot. PHP van is van erre lehetőség bizonyos szerkesztő programokkal, mint a netbeans, vagy eclipse. Kell viszont egy kiegészítő is, amivel a debugolást elvégzi a szerkesztő. Mindkét előbbi szerkesztő programmal használható az xdebug Akit komolyabban érdekel, utánanézhet, mi mindent tud még ez az okos kis program. Például elemezni a program forrást. Futásidőt, memória használatot. Ezzel hatékonyabbé, gyorsabbá tehető egy forráskód, de megteszi az is, ha kiíratsz minden változót, ami hibás lehet, utána egy sortöréssel.
És nem utolsó sorban tanulni, tanulni, tanulni... Lehet hibát keresni, de ha fogalmad sincs, hogy mit keresel, mert nem ismered a nyelv alapjait sem, akkor nehezebben fog menni. Feladni viszont semmiképp nem szabad. Ha órákat, vagy napokat ülsz egy hiba felett, és végül megtalálod, azt sosem felejted el. Míg ha valaki kijavítja helyetted, sosem fog eszedbe jutni.

Ha valaki tud még hasznos módszereket, vagy gyakori hibákat, írja be bátran hozzászólásba.

Kategóriák: 
Megosztás/Mentés

Hozzászólások

deejay94 képe

Hali!

Nagyon jó lett! Írhatnál még ilyeneket ;)

Rimelek képe

Köszi. Ez a cikk már régi, csak most felfrissítettem. A "mindent próbáltam" részt már csak most tettem hozzá.
Majd ahogy időm engedi, természetesen lesznek teljesen frissek is.

viktor0405 képe

Igen tényleg jó lett ez a cikk. Néhány dologban segített.

Suttogó képe

"ahol lehet lépésenként végrehajtani a programot. A PHP nem ilyen nyelv"
A phpban is van lehetőség lépésenként végrehajtani a programot. Ehhez csak egy kiegészítő kell, és egy olyan szerkesztő ami ismeri ezt. Én az xDebug kiegészítőt, és az Eclipse szerkesztőt ajánlom ilyen célra.

Rimelek képe

Igen tudom. és használtam is. Valójában ezt a cikket ugye a phpstudiora írtam még, és akkor még nem ismertem, hogy php-ra is van ilyen megoldás. Amikor beírtam a cikket ide is, el is gondolkodtam, hogy azt ki kéne venni belőle, de elmaradt. Jó is, hogy emlékeztetsz. Átírom most, köszi :)

Dim képe

Kimaradt a nagy PHP bug, a hibalenyelés. Bizonyos esetekben hiába indít a program egy error_reporting(E_ALL); utasítással, ha később include("hibas_php_program.php"); paranccsal behívott fájl hibát tartalmaz, semmi sem jelenik meg sem a képernyőn, sem a logban.
Megoldás: Az include parancs előtt ismét ki kell adni egy error_reporting(E_ALL); parancsot, és máris megkapjuk a hibaüzenetet, ami eddig a semmibe foszlott ...
xDebug-ról pedig vagy jót, vagy semmit. Így én inkább ez utóbbinál maradok...

Rimelek képe

Amit hibalenyelés néven említesz, az a php-fusion cms-ben is úgy láttam, előfordul. Mert valahol error_reporting-gal elrejtik a hibaüzeneteket. Olyan nagyon nem mélyedtem bele a fusion-be, és már régen néztem a forrását. De ha valahol van egy error_reporting(0); akkor akár igen nehéz is lehet eltalálni, hogy hova kell tenni annak felülbírálását, hogy még a hiba előtt, de a hiba elrejtés után legyen. Persze fájlokban keresve lehet kutatni a függvényhívás után. Viszont köszönöm a kiegészítést, mert elvileg az ilyen elnyelt hibák megkeresésére is írtam sok helyen stratégiát, de rákeresve a blogban, itt kimaradt. Majd talán pótlom ezt is. Ha csak az include előtt hívja valaki az error_reporting-ot, az is lehet, hogy az include-ban van elnyeletve a hiba, akkor pedig semmit sem ér. Tehát tovább kell menni mélyebbre. xDebug-ot pedig azét sem részleteztem jobban, mert bevallom én is épp csak hogy ismerem :) De tetszett amit láttam.