Flokkar: Allir, Almennt, Kvikmyndir, PHP, Nörd, Tón- og leiklist

Deila á Facebook
PHP: Debugging
Skrifað af Arnór Heiðar þann 23. nóvember 2005 - 17:20
athugasemdir skrifaðar - toppur / botn
Fjöldi lestra: 1543
Smá um "debugging" í PHP.

Kynning

Oft á dag, lendir maður í því að fólk spyrji mann um hinar ýmsu villur, spyrji mann hvað sé að heilu php skjali, gefur manni jafnvel bara phps og segir: "lagaðu". Þetta verður þreytandi til lengdar, svo að í þessum tutorial, förum við í það, hvernig við finnum út hvað sé að skriptunum okkar. Þetta kallast í daglegu forritaratali "debugging".

Forsendur

Auðvitað geri ég ráð fyrir því að lesandur hafi lesið PHP: Byrjunin, auk þess að hafa leikið sér eitthvað í PHP.

Villur

Villur skiptast alltaf í þrjá flokka: Keyrslu villur (run-time errors), Skrifmáta villur (syntax/parse errors) og Virknis villur (functionality errors).

Skrifmáta villur

Þetta eru augljósustu villurnar. Þetta eru þær villur sem koma bara og stöðva forritið og segja: "hér er eitthvað að, ég get ekki keyrt upp script-ið" og gefa þá yfirleitt upp þá línu sem villan er í. Allar villur sem hafa yfirskriftina 'syntax error' eru svona villur. Þær stafa af því að sá skrifmáti sem PHP býst við að sjá er ekki réttur, td. þegar vantar ; í endann á setningu, strengir eru ekki endaðir/byrjaðir með löppum (' eða ") eða þá að eitthvað er vitlaust skrifað, td. fucntion í stað function.

Til að eiga við svona villur er best að reyna að hugsa eins og PHP-þýðarinn. Hann veit yfirleitt ekkert hvað þú ert að reyna að gera, en veit að það er eitthvað vitlaust. Við skulum sjá smá dæmi...

<?php
$a
= 300;
$b = 222 * 30
echo $a + $b;
?>

Við að keyra þessa scriptu, fáum við villuna: Parse error: parse error, unexpected T_ECHO in draslvilla.php on line 4. Þið hafið eflaust öll lent í að fá þessa villu, maður gerir hana líka þó maður hafi lent í henni 100 sinnum áður (ég). Þetta er auðvitað mjög einfalt dæmi yfir þetta, en oft getur þessi villa gert manni lífið erfitt, þegar maður fattar ekki. En við skulum aðeins líta á hvernig php þýðarinn skilur þetta.

PHP þýðaranum er alveg sama þó það sé línubil þarna hjá okkur, hann heldur bara að setningin sé svona: "$b = 222 * 30 echo $a + $b;" því hann afmarkar allt með semikommunum. Hann býst við að fá +, -, %, ., eða eitthvað annað, en fær echo, þá verður hann reiður.

Við skulum nú líta á annað dæmi:

<?php
function hoppa
{
  echo
'hoppandi glaður';
}
?>

Núna kemur villan: Parse error: parse error, unexpected '{', expecting '(' in draslvilla.php on line 3. Svona villu fáum við mjög oft. unexpected 'foo', expecting 'bar'. Það getur verið erfitt að skilja svona villu. Hér segir hún að villan sé í línu 3, en lína þrjú er bara "{". Þá veit maður oft ekkert hvað maður á að gera, en þannig er mál með vexti að oftast í skrifmátavillum, fáum við línunúmer á línu þar sem er engin villa, því villan er að gerast annarstaðar og hefur þar með áhrif á línuna fyrir neðan.

Þó það eigi ekki alveg heima hér kannski, þá fær maður oft spurningar varðandi parse villur á strengjum, en yfirleitt stafa þær af fákunnáttu um menn eru að gera þegar þeir eru að birta strengi. Mig langar að nefna hér aðeins hvernig maður á að skrifa út strengi.

punktur (.) er notaður til að líma saman strengi og strengja-breytur. Hér ætla ég að setja fram reglu sem ég vil að ALLIR fylgji í einu og öllu, þegar þeir eru byrjendur í PHP. Þetta vil ég gera til að einfalda þeim skilninginn á þessu og til að gera kóðann þeirra pottþéttari (í rauninni er enginn ástæða nokkurntíma til að nota þessa reglu ekki nema bara upp á einhver þægindi):
ÞEGAR VERIÐ ER AÐ LÍMA SAMAN BÚTA AF STRENGJUM OG/EÐA BREYTUM, SKAL ALLTAF HAFA PUNKT Á MILLI, SAMA HVORT UM SÉ AÐ RÆÐA STRENG, TÖLU, FUNCTION-KALL EÐA ANNARSKONAR BREYTU. ENN FREMUR SKAL ALLTAF BYRJA OG ENDA STRENGI Á LÖPPUM (helst ')..
Ef þið fylgið þessari reglu, munið þið aldrei eiga í neinu basli með strengina ykkar. Innrammið hana og hengið upp á vegg. Það skiptir engu máli hversu mörg bil/línubil eru á milli punktanna og breytnanna/strengjanna, það getur þessvegna verið ekkert bil (sem ég er mjög hrifinn af).

Við skulum líta á hoppa fallið aftur:

<?php
function hoppa ()
{
  echo
'hoppandi glaður'.$a.$r['hallo'] 'hallóhahahha';
}
?>

Hér fæ ég villuna: Parse error: parse error, unexpected T_CONSTANT_ENCAPSED_STRING, expecting ',' or ';' in draslvilla.php on line 4. Nú stinga menn oft hausnum í sandinn og spyrja mann hvað sé að þessu. Með nýrri reglu okkar getum við nú bara athugað með hugaraflinu hvað sé í gangi. T_CONSTANT_ENCAPSED_STRING bla bla bla eitthvað voða flókið. NEI. Við bara athugum, samkvæmt reglunni, hvort allir strengir byrji og endi á kommu og hvort það sé ekki örugglega punktur á milli allra breytna/strengja/osfrv. Nei sko, það vantar punkt milli '$r['hallo'] og 'hallóhahahha'. Hlaut að vera...

Keyrslu villur

Í PHP eru keyrslu villur mjög líkar skrifmáta villum, því í PHP keyrist allt forritið upp í einu. Ef maður fær keyrslu villu (þær eru ekkert merktar spes), þá keyrist yfirleitt allt skriptið eða hálft upp, en kemur samt með villu.

Til að skilja þær betur, þurfum við eiginlega að hugsa um hvernig keyrslu villur eru í forritum sem maður keyrir upp (.exe). Það hafa örugglega flestir lent í því að vera í einhverju asna forriti, ýta á takka og þá kemur einhver ljótur windows gluggi með villuskilaboðum. Það er keyrsluvilla. Forritið keyrist upp, en við einhvern ákveðinn atburð, þá verður villa sem birtist mjög augljóslega með látum. En eins og ég sagði áðan þá er PHP forrit bara keyrt upp og lokað strax svo maður situr oft uppi með villu sem lítur út eins og það sé eitthvað að skrifmátanum, þannig að maður fer að leita að semikommum sem vantar, punktum eða einhverju álíka.

Dæmi um keyrsluvillu:

<?php
echo 'blabla';
echo
'límist saman við '.flogiston().' þetta.';
?>

Við þetta kemur villan: Fatal error: Call to undefined function: flogiston() in draslvilla.php on line 2. Sem betur fer eru yfirleitt betri villuboð sem fylgja keyrsluvillum. Það er augljóst að hér er enginn flogiston() function skilgreindur, það kemur fatal error, en samt keyrist skriptið upp þar á undan (það echo-ast 'blabla').

Virknis villur
Þessar villur eru erfiðastar, því allt skriptið keyrist upp, án þess að PHP birti augljósa villu. Dæmi um svona villu er þegar maður er kannski að lesa úr stóru array-i og echo-a því svo út, að þá komi bara ekki neitt úr array-inu. Maður skilur ekkert í því og brýtur heilan oft í margar klukkustundir (næstum því ;D). Ástæðan getur verið rosalega mismunandi. Ekkert kemur úr gagnagrunni, maður kallar vitlaust í breytur, ofl.

Við skulum enn og aftur nefna dæmi um villu:

<?php
$ar
= array ();
$ar[] = 'halló, ég er strengur númer eitt';
$ar[] = 'halló, ég er næsti strengur';
echo
$ar;
?>

Villan sem kemur út úr þessu: Engin. Skjárinn er einfaldlega tómur. Hér er nú augljóst að maður hefði átt að kalla í þessa breytu með $ar[0] eða $ar[1], en hér er annað dæmi:

<?php
$ar
= array ();
$ar[] = 'halló, ég er strengur númer eitt';
$ar[] = 'halló, ég er næsti strengur';
echo
$ar[2];
?>

Hér reynum við að birta streng númer 2. Það virkar auðvitað ekki, en það sem er athyglisvert við þetta dæmi, er að það kemur villa, eða öllu heldur áminning: Notice: Undefined offset: 2 in draslvilla.php on line 5. Svona villu getur verið hrikalega erfitt að finna.

Nú skulum við prufa enn eina villuna:

<?php
mysql_connect
('localhost','user','pass');
mysql_select_db('grunnur');
$nafn_a_toflu = 'tafla2003';
$res = mysql_query('select'.' *'.' from '.$nafn_a_toflu.', order by field');
while (
$row = mysql_fetch_array($res)) {
  echo
$row['field'];
}
?>

Ef við segjum sem svo að búið sé að búa til þennan grunn, þessa töflu og þennan field í töflunni, þá hefði maður haldið að þetta virkaði. En hvað gerist? Við fáum villuna: Warning: mysql_fetch_array(): supplied argument is not a valid MySQL result resource in draslvilla.php on line 5. Hmmm... supplied argument is nota valid resoure. Þessi villa kemur þegar við köllum í mysql_fetch_array() með breytu sem ekki er mysql result resource. En $res er result breyta... eða hvað?

Nú skulum við nota sterkasta debugging tólið í PHP: echo. Við echo-um $res breytunni og fáum EKKERT. Dem. Það er skrýtið, því ef þetta virkaði, kæmi eitthvað eins og: Resource id #3.

Þá getum við notað næst besta debugging tólið í PHP: var_dump(). var_dump() birtir allar upplýsingar um breytu. Þá notum við það og segjum: var_dump($res); Hvað fáum við? 'bool(false)'. Það þýðir að þessi breyta er boolean breyta og hefur gildið 'false'. Sem, aftur, þýðir að mysql_query() er ekki að heppnast, sem þýðir, enn og aftur, að eitthvað sé að fyrirspurninni okkar.

Ekki er auðvelt að sjá hver villan er í þessari fyrirspurn, því hún er svo samsett. Þá er gott trix að breyta þessu aðeins og gera svona:

<?php
mysql_connect
('localhost','user','pass');
mysql_select_db('grunnur');
$nafn_a_toflu = 'tafla2003';
$sql = 'select'.' *'.' from '.$nafn_a_toflu.', order by field';
$res = mysql_query($sql);
while (
$row = mysql_fetch_array($res)) {
  echo
$row['field'];
}
?>

Þá getum við bara gert: echo $sql;. Þá sjáum við betur, að það er komma á undan 'order by' og það á ekki að vera. Við breytum og þá virkar þetta alltsaman.

Nú skulum við setja fram aðra reglu (sem er reyndar nokkuð erfiðara að fylgja eftir, því oft veit maður ekki hvað maður á að prenta út):
EF EITTHVAÐ VIRKAR EKKI RÉTT ER BEST AÐ ECHO-A ÖLLUM ÞEIM BREYTUM SEM HEFUR ÁHRIF Á SETNINGUNA SEM BILAR, EF ÞAÐ VIRKAR EKKI NOTUM VIÐ var_dump() OG EF ÞAÐ VIRKAR EKKI HELDUR, NOTUM VIÐ print_r().
print_r() og var_dump eru nokkuð svipaðir, en print_r er mun þægilegra, sérstaklega á array, en er ekki alveg nógu klárt.

Eitt snilldartólið í viðbót sem við getum kannski minnst á hér, en það er fyrir að debugga mysql fyrirspurnir. Til að vita hvaða villu mysql gaf á einhverja fyrirspurn, getum við kallað í fallið mysql_error(), það skilar okkur lýsingu á sql-villunni.




Athugasemdir ():