Debuggen: het oplossen van PHP fouten
Een belangrijk aspect van het programmeren waarmee ik deze tutorial wil afsluiten, is het debuggen van je scripts. Alle programmeur zijn mensen en mensen maken fouten. We kunnen dus ook niet voorkomen dat er foutjes in onze scripts sluipen waardoor een script niet zal werken.
Dit hoeft echter helemaal geen probleem te zijn, aangezien je fouten kunt oplossen. Het debuggen van je script bestaat dan ook uit 3 stappen:
Constateren van een fout
De fout lokaliseren in je script
Oplossen van de fout
Voordat we hier echter mee beginnen, eerst iets anders. We willen immers wel dat PHP ook daadwerkelijk foutmeldingen gaat geven als er iets fout gaat. Daarom zetten we van nu af aan altijd deze twee regels boven aan onze php scripts:
De eerste regel zorgt ervoor dat fouten überhaupt weergegeven worden, terwijl de tweede regel ervoor zorgt dat alle mogelijke foutmeldingen op het scherm getoond worden.
Regels toegevoegd maar geen fouten te zien?
Het kan zijn dat de display_errors instelling in de php.ini uitgeschakeld staat. Hoewel we hem in ons script met ini_set() aan zetten, wordt dit pas gedaan als het script uitgevoerd wordt. Eventuele syntax fouten in het script worden dus nog niet weergegeven.
Om dat voor elkaar te krijgen, plaatsen we een .htaccess bestandje met de volgende regels in de root (public_html, www of htdocs map) van onze website:
Nu worden alle foutmeldingen netjes op het scherm getoond.
Debuggen
Ik zal een aantal voorbeelden geven van de meest voorkomende fouten in een PHP script. Bij elk voorbeeld zullen we vervolgens aan de hand van de drie stappen van het debuggen de fout proberen te verhelpen.
De eerste stap, het constateren van de fout, is de minst lastige. PHP zal namelijk een foutmelding op het scherm zetten en al dan niet het script stoppen. De syntax van de standaard PHP foutmelding ziet er er als volgt uit:
De tweede stap zal in de meeste gevallen de lastigste zijn. In de foutmelding wordt altijd een bestand en regelnummer gegeven waar de fout optreedt. Dat geeft ons een indicatie van waar iets fout gaat en gecombineerd met het bericht leidt ons dat meestal wel naar de fout.
De derde stap is weer heel eenvoudig. Immers, als je weet wat er fout gaat, kun je het ook heel eenvoudig oplossen.
Debuggen is een techniek die je jezelf moet aanleren. Goed kunnen debuggen zul je niet in 1x kunnen, daar komt ook een stukje ervaring bij kijken. Laten we daarom gewoon maar eens beginnen en naar wat veel voorkomende fouten en oplossingen kijken.
Parse error
2
3
4
5
6
7
ini_set('display_errors', 'On');
error_reporting(E_ALL);
$sNaam = 'Kees'
echo $sNaam;
?>
Deze foutmelding geeft aan dat we een fout in de syntax van ons script hebben, en wel op regel 6 in fouten.php. PHP geeft aan dat hij een bepaald element niet verwacht: 'syntax error, unexpected T_ECHO'. Met andere woorden, de echo op regel 6 komt onverwacht.
Om de fout te lokaliseren zullen we vanaf regel 6 terug moeten gaan kijken, op zoek naar de reden waarom de echo onverwacht is. In veel gevallen zal het zo zijn dat je ergens een punt-komma, quote of haakje vergeten bent.
De fout is hier snel gevonden, we zien namelijk dat we vergeten zijn om regel 5 met een punt-komma af te sluiten. De oplossing is dus het plaatsen van de punt-komma.
PHP zal altijd aangeven welk element niet verwacht wordt. Soms wordt het teken weergeven, soms een omschrijving. Enkele omschrijvingen die je regelmatig ziet:
T_VARIABELE - Een variabele
T_IS_EQUAL - Een == teken
Undefined variable
Deze foutmelding vertelt ons dat er op regel 5 in fouten.php iets fout gegaan is. Het bericht 'Undefined variable: sNaam' houdt in dat we een variabele $sNaam gebruikt hebben die niet bestaat. De oplossing is dus ofwel het eerder declareren van deze variabele, ofwel eerst controleren of deze variabele bestaat voordat we hem gebruiken:
2
3
4
5
6
7
ini_set('display_errors', 'On');
error_reporting(E_ALL);
$sNaam = 'Kees';
echo $sNaam;
?>
2
3
4
5
6
7
8
9
ini_set('display_errors', 'On');
error_reporting(E_ALL);
if(isset($sNaam))
{
echo $sNaam;
}
?>
Undefined index
De undefined index is bijna hetzelfde als de undefined variabele. Deze foutmelding wordt namelijk weergegeven als een bepaalde sleutel in een array niet bestaat. De oplossing is hier wederom het eerst controleren of de variabele bestaat voordat je hem gebruikt:
2
3
4
5
6
7
8
9
ini_set('display_errors', 'On');
error_reporting(E_ALL);
if(isset($_GET['naam']))
{
echo $_GET['naam'];
}
?>
Parse errors: unexpected $end
2
3
4
5
6
7
8
ini_set('display_errors', 'On');
error_reporting(E_ALL);
if(isset($_GET['naam']))
{
echo $_GET['naam'];
?>
Dit zijn meestal vervelendere fouten om op te moeten lossen. Met name omdat deze fout altijd plaatsvindt op de laatste regel van je script.
De oorzaak is bijna altijd dat het aantal { niet gelijk is aan het aantal } in je script waardoor er dus bepaalde constructies niet afgesloten zijn. In het voorbeeld is direct duidelijk dat we de } van het if-statement vergeten zijn. Maar naarmate je code langer wordt, kan dit een ware zoektocht opleveren. En dan blijkt maar weer hoe belangrijk het is om netjes te scripten!
Header already sent
2
3
4
5
6
7
ini_set('display_errors', 'On');
error_reporting(E_ALL);
echo 'Hello World!';
header('Refresh: 3; url=index.php');
?>
Dit is een veel voorkomende fout waar veel beginnende programmeurs moeite mee hebben. Hij wordt veroorzaakt doordat je voor de functies header(), session_start() en setcookie() nog helemaal geen output naar de browser verzonden mag hebben. Dat betekent geen echo, geen HTML maar ook geen loze spatie ergens buiten je php tags.
De foutmelding geeft ons ten eerste weer het script en regelnummer waar de fout is opgetreden. De melding geeft aan dat het een 'headers already sent' fout betreft. Verder geeft de foutmelding ook nog aan waar er al output naar de browser verzonden is. In ons geval in fouten.php op regel 5. En dat klopt, want daar staat onze echo.
De oplossing van deze fouten is niet altijd even eenvoudig. Waar je altijd op moet proberen te letten is dat je altijd eerst alle logica (php) afhandelt voordat je output (HTML) gaat genereren. In ons geval zullen we de header() dus voor de echo moeten plaatsen:
2
3
4
5
6
7
ini_set('display_errors', 'On');
error_reporting(E_ALL);
header('Refresh: 3; url=index.php');
echo 'Hello World!';
?>
Ik krijg niets te zien?
Als je een lege pagina terug krijgt terwijl je toch echt output verwacht, zul je nog even goed naar je script moeten kijken. Controleer even of er wel degelijk output gegeven zou moeten worden.
In het andere geval zou het kunnen dat de display_errors instelling uit staat waardoor fouten helemaal niet weergegeven worden. Hoewel we dat telkens met die eerste twee regels code aanzetten, gebeurt dit pas op een moment nadat bijvoorbeeld parse errors opgetreden zijn. Deze worden dan alsnog niet weergegeven.
Dat kunnen we oplossen door een bestandje met de naam .htaccess (ja een punt als begin en verder geen extensie) in de root van onze website te zetten. In dit bestandje zetten we dan de volgende regel:
Nu staat de display_errors instelling ingeschakeld en worden ook de parse errors weergegeven.
Voor meer informatie over foutafhanding in PHP verwijs ik je graag door naar mijn tutorial over foutafhandeling in PHP. Daar ga ik veel dieper in op de verschillende mogelijkheden die je hebt met betrekking tot het afhandelen van fouten in PHP.
Inhoudsopgave
- Inleiding
- Mijn eerste PHP script
- Variabelen
- Statements
- Loops
- Arrays
- Functies
- Formulieren
- Superglobals
- Sessies nader bekeken: een eerste loginscript
- Netjes scripten
- Debuggen: het oplossen van PHP fouten
- Slotwoord en referenties