PDO - Verbinden met verschillende databases
- Inleiding
- Gebruik van de PDO extensie
- Uitvoeren van queries
- Foutafhandeling
- Prepared statements
- Transacties
- Slotwoord en referenties
- Reacties op deze tutorial
Foutafhandeling
In de voorbeelden op de vorige pagina heb ik nog geen enkele vorm van foutafhandeling toegepast, maar natuurlijk mag dat niet vergeten worden. Foutafhandeling in een php script is een van de belangrijkste dingen die er zijn.PDO biedt drie verschillende manieren van foutafhandeling.
- SILENT - Fouten worden onderdrukt en zullen handmatig opgevraagd moeten worden
- WARNING - Gebruikt de error_handler van PHP en geeft een E_WARNING
- EXCEPTION - Gebruikt PDOException klasse
Van dit lijstje is SILENT de standaard instelling. Dat betekent dat je altijd de code en informatie van de foutmelding met de methodes errorInfo() en errorCode() zult moeten ophalen om te controleren of er fouten opgetreden zijn. Een uitzondering op deze regel is een fout bij het verbinden met de database, oftewel het instantieren van de PDO klasse. In dat geval wordt er een PDOException object aangemaakt dat af te vangen is met een try/catch combinatie.
Voorbeeld 11: Foutmelding van verbinding afvangen
Code
1
2
3
4
5
6
7
8
9
10
2
3
4
5
6
7
8
9
10
<?php
try
{
$db = new PDO('mysql:host=localhost;dbname=bestaat_niet','user','password');
}
catch(PDOException $e)
{
echo $e->getMessage();
}
?>
try
{
$db = new PDO('mysql:host=localhost;dbname=bestaat_niet','user','password');
}
catch(PDOException $e)
{
echo $e->getMessage();
}
?>
Dit zal de volgende melding geven:
Code
1
SQLSTATE[42000] [1049] Unknown database 'bestaat_niet'
Zoals we zien krijgen we netjes een melding dat de opgegevens database niet bestaat.
Het is van belang dat wel altijd op deze manier controleren of een verbinding gelukt is. Mocht er namelijk iets fout gaan en de fout wordt niet afgevangen, dan zal PHP een backtrace weergeven waarin mogelijk alle details van de database verbinding staan. Dit omvat dus mogelijk ook gegevens als gebruikersnaam en wachtwoord van je database!
Als we met de standaard instelling een fout maken in een query die we uitvoeren, krijgen we daar geen foutmelding van te zien.
Voorbeeld 12: Fout in query
Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<?php
try
{
$db = new PDO('mysql:host=localhost;dbname=test','user','password');
$sql = "SELECT naam FROM bestaat_niet";
$results = $db->query($sql);
foreach($results as $row)
{
echo $row['naam'].'<br>';
}
}
catch(PDOException $e)
{
echo $e->getMessage();
}
?>
try
{
$db = new PDO('mysql:host=localhost;dbname=test','user','password');
$sql = "SELECT naam FROM bestaat_niet";
$results = $db->query($sql);
foreach($results as $row)
{
echo $row['naam'].'<br>';
}
}
catch(PDOException $e)
{
echo $e->getMessage();
}
?>
De enige melding die we nu krijgen is:
Code
1
Warning: Invalid argument supplied for foreach() in /Users/jorendewit/Sites/jorendewit/phphulp/pdo.php on line 9
We zien dat $results dus geen geldig argument voor de foreach() is en dus doet dat ons vermoeden dat er iets fout gegaan is met de query. Maar als dat zo is, willen we daar eigenlijk gewoon een foutmelding van krijgen.
In dat geval zouden we ervoor kunnen kiezen om de WARNING instelling te gebruiken. In dat geval wordt er naast het aanmaken van een error code ook een standaard E_WARNING melding gegeven.
Het type foutafhandeling kunnen we instellen door het type toe te kennen aan het attribuut dat de foutafhandeling bepaald. Dit doen we met de setAttribute() methode.
Voorbeeld 13: Foutafhandeling met WARNING
Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<?php
try
{
$db = new PDO('mysql:host=localhost;dbname=test','user','password');
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_WARNING);
$sql = "SELECT naam FROM bestaat_niet";
$results = $db->query($sql);
foreach($results as $row)
{
echo $row['naam'].'<br>';
}
}
catch(PDOException $e)
{
echo $e->getMessage();
}
?>
try
{
$db = new PDO('mysql:host=localhost;dbname=test','user','password');
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_WARNING);
$sql = "SELECT naam FROM bestaat_niet";
$results = $db->query($sql);
foreach($results as $row)
{
echo $row['naam'].'<br>';
}
}
catch(PDOException $e)
{
echo $e->getMessage();
}
?>
De foutmelding die nu gegeven wordt:
Code
1
2
3
2
3
Warning: PDO::query() [function.PDO-query]: SQLSTATE[42S02]: Base table or view not found: 1146 Table 'test.bestaat_niet' doesn't exist in /Users/jorendewit/Sites/jorendewit/phphulp/pdo.php on line 8
Warning: Invalid argument supplied for foreach() in /Users/jorendewit/Sites/jorendewit/phphulp/pdo.php on line 10
Warning: Invalid argument supplied for foreach() in /Users/jorendewit/Sites/jorendewit/phphulp/pdo.php on line 10
We zien dat er zowel een foutmelding gegeven wordt op het punt waar de query uitgevoerd wordt als op de plaats van de foreach(). Zoals je altijd te werk gaat met debuggen, los je nu ook eerst de eerste fout op. Dit zal in dit geval ook de tweede foutmelding laten verdwijnen.
Als laatste instelling hebben we EXCEPTION over. In dat geval zal er net zoals in het geval van de fout met de verbinding, voor de fout een PDOException object aangemaakt worden. De gegevens van deze foutmelding kunnen we wederom uitlezen in het catch gedeelte van het script.
Voorbeeld 14: Exception als foutafhandeling
Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<?php
try
{
$db = new PDO('mysql:host=localhost;dbname=test','user','password');
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$sql = "SELECT naam FROM bestaat_niet";
$results = $db->query($sql);
foreach($results as $row)
{
echo $row['naam'].'<br>';
}
}
catch(PDOException $e)
{
echo $e->getMessage();
}
?>
try
{
$db = new PDO('mysql:host=localhost;dbname=test','user','password');
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$sql = "SELECT naam FROM bestaat_niet";
$results = $db->query($sql);
foreach($results as $row)
{
echo $row['naam'].'<br>';
}
}
catch(PDOException $e)
{
echo $e->getMessage();
}
?>
De volgende foutmelding is gegenereerd:
Code
1
SQLSTATE[42S02]: Base table or view not found: 1146 Table 'test.bestaat_niet' doesn't exist
We zien dat we hier alleen een foutmelding op de query te zien krijgen en geen verdere meldingen dat bijvoorbeeld het argument van de foreach() niet juist is.
Zoals gewoonlijk kunnen we natuurlijk het hele PDOException object uitkleden en alle informatie over een fout naar boven halen.
Voorbeeld 15: Uitgebreide foutmelding
Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<?php
try
{
$db = new PDO('mysql:host=localhost;dbname=test','user','password');
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$sql = "SELECT naam FROM bestaat_niet";
$results = $db->query($sql);
foreach($results as $row)
{
echo $row['naam'].'<br>';
}
}
catch(PDOException $e)
{
echo '<pre>';
echo 'Regelnummer: '.$e->getLine().'<br>';
echo 'Bestand: '.$e->getFile().'<br>';
echo 'Foutmelding: '.$e->getMessage().'<br>';
echo '</pre>';
}
?>
try
{
$db = new PDO('mysql:host=localhost;dbname=test','user','password');
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$sql = "SELECT naam FROM bestaat_niet";
$results = $db->query($sql);
foreach($results as $row)
{
echo $row['naam'].'<br>';
}
}
catch(PDOException $e)
{
echo '<pre>';
echo 'Regelnummer: '.$e->getLine().'<br>';
echo 'Bestand: '.$e->getFile().'<br>';
echo 'Foutmelding: '.$e->getMessage().'<br>';
echo '</pre>';
}
?>
Code
1
2
3
2
3
Regelnummer: 8
Bestand: /Users/jorendewit/Sites/jorendewit/phphulp/pdo.php
Foutmelding: SQLSTATE[42S02]: Base table or view not found: 1146 Table 'test.bestaat_niet' doesn't exist
Bestand: /Users/jorendewit/Sites/jorendewit/phphulp/pdo.php
Foutmelding: SQLSTATE[42S02]: Base table or view not found: 1146 Table 'test.bestaat_niet' doesn't exist
Ik zou aanraden om de Exception te gebruiken als foutafhandeling. Je gebruikt de try/catch syntax immers toch al om te controleren of de verbinding gelukt is. Daarnaast krijg je alle opvolgende foutmeldingen die het gevolg zijn van een foute query niet te zien en kun je helemaal zelf bepalen welke informatie je wel wilt tonen.