Tutorials
MySQLi - Een nieuwe manier van interactie tussen PHP en MySQ
Uitgebreide tutorial over het gebruik van de MySQLi extensie van PHP 5 voor interactie met een MySQL databaseserver.
Pagina 1
Inleiding
Sinds midden jaren 90 heeft de mysql extensie van PHP dienst gedaan als brug tussen PHP en MySQL. Iedereen is wel bekend met de mysql_* functies die je gebruikt om acties op een MySQL database uit te voeren. De mysql extensie heeft al die tijd zijn werk eigenlijk prima gedaan.
In de loop der jaren echter zijn er zowel in PHP als MySQL veel dingen veranderd en sinds de komst van PHP 5 en MySQL 4.1 begon de mysql extensie steeds meer gebreken te vertonen. Het belangrijkste gebrek is misschien wel de incompatibiliteit met sommige nieuwe features die vanaf MySQL 4.1 beschikbaar zijn. Vandaar dat het op een gegeven moment tijd werd om een hele nieuwe extensie te schrijven. Deze extensie, die sinds PHP 5 beschikbaar is, kreeg de naam mysqli. De i in deze naam staat voor improved.
Het belangrijkste doel van de mysqli extensie is het zorgen voor compatibiliteit met de nieuwste functies van de database server. Daarnaast biedt deze nieuwe extensie naast de bekende (procedurale) manier van werken met een database ook een object georienteerde interface voor interactie met de database server. Deze methode zullen we nog veelvuldig tegenkomen.
Waarom zou je overstappen op het gebruik van mysqli? Allereerst krijg je natuurlijk beschikking over de nieuwe features van MySQL 4.1 en hoger. Daarnaast is performace een belangrijke factor. De meeste acties die uitgevoerd kunnen worden zijn sneller geworden en acties zijn nu tot 40x sneller uit te voeren. En misschien nog wel de belangrijkste reden: de mysql extensie zit in de laatste jaren van zijn bestaan. Dit betekent dat vanaf PHP 6 de mysql_* functies niet meer ondersteund zullen worden.
In deze tutorial zal ik een uitgebreid overzicht geven van de vele mogelijkheden die deze nieuwe extensie je biedt. Ik zal vrij eenvoudig beginnen met voorbeelden van het verbinden met de database en eenvoudige queries en zal gelijk aan verder gaan met complexere toepassingen. Onder andere het uitvoeren van meerdere queries in een enkele stap, het gebruik van prepared statements en functies als commit() en rollback() zullen besproken worden.
De nadruk zal in deze tutorial liggen op verschillende manieren van het uitvoeren van database queries, niet op de inhoud van de queries op zich.
Benodigde voorkennis
[li]Basiskennis PHP[/li]
[li]Werken met databases in PHP[/li]
[li]Basiskennis SQL[/li]
[li]Basiskennis van object georienteerd programmeren[/li]
Systeemeisen
[li]PHP >= 5.0.0[/li]
[li]MySQL >= 4.1[/li]
[li]Geactiveerde mysqli extensie (controleer phpinfo() op een kopje 'mysqli')[/li]
Opmerking
Ik weet dat er reeds een tutorial over dit onderwerp geschreven is door Webmakerij en wil daar ook helemaal niets aan af doen. Aan deze tutorial was ik ooit al eens begonnen en heb nu eindelijk tijd gevonden om hem af te maken. Omdat deze tutorial een stukje uitgebreider is, wil ik hem jullie niet onthouden.
In de loop der jaren echter zijn er zowel in PHP als MySQL veel dingen veranderd en sinds de komst van PHP 5 en MySQL 4.1 begon de mysql extensie steeds meer gebreken te vertonen. Het belangrijkste gebrek is misschien wel de incompatibiliteit met sommige nieuwe features die vanaf MySQL 4.1 beschikbaar zijn. Vandaar dat het op een gegeven moment tijd werd om een hele nieuwe extensie te schrijven. Deze extensie, die sinds PHP 5 beschikbaar is, kreeg de naam mysqli. De i in deze naam staat voor improved.
Het belangrijkste doel van de mysqli extensie is het zorgen voor compatibiliteit met de nieuwste functies van de database server. Daarnaast biedt deze nieuwe extensie naast de bekende (procedurale) manier van werken met een database ook een object georienteerde interface voor interactie met de database server. Deze methode zullen we nog veelvuldig tegenkomen.
Waarom zou je overstappen op het gebruik van mysqli? Allereerst krijg je natuurlijk beschikking over de nieuwe features van MySQL 4.1 en hoger. Daarnaast is performace een belangrijke factor. De meeste acties die uitgevoerd kunnen worden zijn sneller geworden en acties zijn nu tot 40x sneller uit te voeren. En misschien nog wel de belangrijkste reden: de mysql extensie zit in de laatste jaren van zijn bestaan. Dit betekent dat vanaf PHP 6 de mysql_* functies niet meer ondersteund zullen worden.
In deze tutorial zal ik een uitgebreid overzicht geven van de vele mogelijkheden die deze nieuwe extensie je biedt. Ik zal vrij eenvoudig beginnen met voorbeelden van het verbinden met de database en eenvoudige queries en zal gelijk aan verder gaan met complexere toepassingen. Onder andere het uitvoeren van meerdere queries in een enkele stap, het gebruik van prepared statements en functies als commit() en rollback() zullen besproken worden.
De nadruk zal in deze tutorial liggen op verschillende manieren van het uitvoeren van database queries, niet op de inhoud van de queries op zich.
Benodigde voorkennis
[li]Basiskennis PHP[/li]
[li]Werken met databases in PHP[/li]
[li]Basiskennis SQL[/li]
[li]Basiskennis van object georienteerd programmeren[/li]
Systeemeisen
[li]PHP >= 5.0.0[/li]
[li]MySQL >= 4.1[/li]
[li]Geactiveerde mysqli extensie (controleer phpinfo() op een kopje 'mysqli')[/li]
Opmerking
Ik weet dat er reeds een tutorial over dit onderwerp geschreven is door Webmakerij en wil daar ook helemaal niets aan af doen. Aan deze tutorial was ik ooit al eens begonnen en heb nu eindelijk tijd gevonden om hem af te maken. Omdat deze tutorial een stukje uitgebreider is, wil ik hem jullie niet onthouden.
Pagina 2
Transacties met mysqli: commit() en rollback()
Transacties klinken de doorgewinterde databasegebruiker waarschijnlijk zeer bekend in de oren, maar niet iedereen zal weten wat je met dit principe kunt. Simpel gezegd heb je bij transacties in een database de mogelijkheid om een reeks queries uit te voeren zonder dat je eventuele aanpassingen definitief doorvoert. Aan het einde van deze reeks kun je COMMIT gebruiken om de wijzigingen definitief door te voeren of ROLLBACK om alle wijzigingen terug te draaien.
Transacties kun je volledig verwerken in je sql query, maar de mysqli extensie biedt daar een andere manier voor. Voor het gebruik van deze methode zul je de InnoDB engine van MySQL moeten gebruiken. De andere engines zoals MyISAM ondersteunen deze functionaliteit niet.
In het volgende voorbeeld zal ik een transactie gebruiken om verschillende records in een database in te voegen.
Voorbeeld 14: Transactie met mysqli
<?php
$mysqli = new mysqli('host', 'user', 'password', 'database');
if(mysqli_connect_errno())
{
trigger_error('Fout bij verbinding: '.$mysqli->error);
}
$mysqli->autocommit(FALSE);
$mysqli->query("INSERT INTO tabel (naam) VALUES ('Piet')");
$mysqli->query("INSERT INTO tabel (naam) VALUES ('Karel')");
$mysqli->query("INSERT INTO tabel (naam) VALUES ('Kees')");
$mysqli->commit();
?>
Dit is de standaard manier waarop een transactie opgebouwd wordt. Allereerst zetten we met behulp van de autocommit() methode de waarde van autocommit op FALSE. Dit zorgt ervoor dat queries nog niet definities uitgevoerd worden in de database. Vervolgens voeren we de betreffende queries uit en gebruiken we de commit() methode om de aanpassingen definitief door te voeren.
Nu is dit echt het meest basale voorbeeld dat geen enkel voordeel heeft ten opzichte van het normaal uitvoeren van deze queries. Wat hebben we dan eigenlijk aan transacties en hoe kunnen we daar ons voordeel mee doen?
Allereerst kun je transacties gebruiken om een reeks queries ongedaan te maken zodra er een query niet correct uitgevoerd wordt.
Voorbeeld 15: Ongedaan maken van een reeks queries
<?php
$mysqli = new mysqli('host', 'user', 'password', 'database');
if(mysqli_connect_errno())
{
trigger_error('Fout bij verbinding: '.$mysqli->error);
}
// Queries definieren
$queries[] = "INSERT INTO tabel (naam) VALUES ('Piet')";
$queries[] = "INSERT INTO tabel (naam) VALUES ('Karel')";
$queries[] = "INSERT INTO tabel (naam) ('Kees')";
// Zet autocommit op FALSE
$mysqli->autocommit(FALSE);
// Voer de queries uit en controleer of ze gelukt zijn
foreach($queries as $query)
{
if(!$mysqli->query($query))
{
$errors[$query] = $mysqli->error;
}
}
// ROLLBACK of COMMIT
if(isset($errors))
{
$mysqli->rollback();
foreach($errors as $sql => $error)
{
echo '<pre>'.$error.' in SQL: '.$sql.'</pre>';
}
}
else
{
$mysqli->commit();
}
?>
De reeks queries die we achter elkaar willen uitvoeren zetten we in de array $queries. We zetten autocommit wederom op FALSE en gebruiken nu een foreach loop om de queries uit te voeren. Als er nu een query mislukt, wordt er een foutmelding toegevoegd aan de $errors array.
Door vervolgens te controleren of de $errors array bestaat, weten we direct of er fouten opgetreden zijn. Zo ja, dan gebruiken we de rollback() methode om alle queries ongedaan te maken en geven we de opgetreden fouten weer. Zijn er geen fouten opgetreden, dan gebruiken we de commit() methode om de aanpassingen definitief door te voeren.
In dit geval zal er niets in onze tabel veranderen omdat de laatste query zeker zal mislukken.
Voorbeeld 16: Werking ROLLBACK
<?php
$mysqli = new mysqli('host', 'user', 'password', 'database');
if(mysqli_connect_errno())
{
trigger_error('Fout bij verbinding: '.$mysqli->error);
}
$verwijder = "DELECT FROM klanten";
$selecteer = "SELECT COUNT(*) AS aantal FROM klanten";
// Zet autocommit op FALSE
$mysqli->autocommit(FALSE);
// Verwijder alle gegevens uit de klanten tabel
$mysqli->query($verwijder);
// Kijk hoeveel records er in de klanten tabel staan
$result = $mysqli->query($selecteer);
$row = $result->fetch_assoc();
echo 'Er staan '.$row['aantal'].' records in de klanten tabel <br>';
// ROLLBACK
$mysqli->rollback();
// Kijk wederom hoeveel records er in de klanten tabel staan
$result = $mysqli->query($selecteer);
$row = $result->fetch_assoc();
echo 'Er staan '.$row['aantal'].' records in de klanten tabel <br>';
?>
In dit scriptje laat ik zien wat de rollback() methode nou precies doet. Allereerst maar eens de output van het script:
Nadat we eerst alle records uit de klanten tabel verwijderd hebben, kijken we hoeveel records nog aanwezig zijn. Zoals het eerste resultaat ook aangeeft is dat er geen een meer. Echter na het uitvoeren van de rollback() methode staan er weer records in de klanten tabel. Het blijkt dus dat onze eerder uitgevoerde DELETE query ongedaan is gemaakt.
Let op dat ik dit script helemaal geen foutafhandeling toegepast heb. Normaal gesproken mag dat natuurlijk niet ontbreken!
Om het gebruik van transacties verder te verduidelijken, zal ik een voorbeeld uit de boeken geven. Dit voorbeeld betreft een geldtransactie tussen twee bankrekeningen van respectievelijk persoon A en B.
Het gaat hier om een overschrijving van 1000 euro van de rekening van persoon A naar die van persoon B. De voorwaarde waarop dit uitgevoerd kan worden is dat persoon A genoeg geld op zijn rekening heeft.
Voorbeeld 17: Overschrijving tussen twee rekeningen
<?php
$mysqli = new mysqli('host', 'user', 'password', 'database');
if(mysqli_connect_errno())
{
trigger_error('Fout bij verbinding: '.$mysqli->error);
}
// Queries
$queries[] = "UPDATE rekeningen SET saldo = saldo - 1000 WHERE klant = 'A'";
$queries[] = "UPDATE rekeningen SET saldo = saldo + 1000 WHERE klant = 'B'";
// Controle query
$controle = "SELECT saldo FROM rekeningen WHERE klant = 'A'";
// Zet autocommit op FALSE
$mysqli->autocommit(FALSE);
// Uitvoeren van queries en controleren of ze gelukt zijn
foreach($queries as $query)
{
if(!$result = $mysqli->query($query))
{
$errors[$query] = $mysqli->error;
}
if($mysqli->affected_rows == 0)
{
$errors[$query] = 'Er zijn geen rijen gewijzigd in SQL';
}
}
// Uitvoeren controle query en controleren waarde
if(!$result = $mysqli->query($controle))
{
$errors[$controle] = $mysqli->error;
}
else
{
$row = $result->fetch_assoc();
if($row['saldo'] < 0)
{
$errors[$controle] = 'Het saldo op een rekening is niet toereikend.';
}
}
// ROLLBACK of COMMIT
if(isset($errors))
{
$mysqli->rollback();
foreach($errors as $sql => $error)
{
echo '<pre>'.$error.' SQL: '.$sql.'</pre>';
}
}
else
{
$mysqli->commit();
}
?>
De UPDATE queries zorgen ervoor dat er 1000 van de rekening van persoon A gehaald wordt en bij het saldo van persoon B opgeteld wordt. De controle query haalt ter controle het nieuwe saldo persoon A op, dit mag immers niet negatief zijn.
Allereerst voeren we de update queries uit, kijken we of ze gelukt zijn en of er daadwerkelijk gegevens in de database aangepast zijn. Vervolgens voeren we de controle query uit en controleren we het saldo van persoon A.
Als er ergens in deze transactie fouten opgetreden zijn, draaien we alles terug met rollback() en geven we de foutmeldingen weer. Is het goed gegaan, dan maken we de overboeking definitief met de commit() methode.
Het gebruik van een transactie is hier een vereiste omdat het totale saldo in de tabel natuurlijk gelijk moet blijven. Er kan niet zomaar geld aangemaakt of vernietigd worden. Het grote voordeel is daarnaast dat tijdens de transactie het voor andere gebruikers niet mogelijk is om deze gegevens te wijzigen. Het kan dus nooit zo zijn dat twee gebruikers precies tegelijkertijd dezelfde gegevens wijzigen waardoor de data mogelijk corrupt kan raken.
Transacties kun je volledig verwerken in je sql query, maar de mysqli extensie biedt daar een andere manier voor. Voor het gebruik van deze methode zul je de InnoDB engine van MySQL moeten gebruiken. De andere engines zoals MyISAM ondersteunen deze functionaliteit niet.
In het volgende voorbeeld zal ik een transactie gebruiken om verschillende records in een database in te voegen.
Voorbeeld 14: Transactie met mysqli
<?php
$mysqli = new mysqli('host', 'user', 'password', 'database');
if(mysqli_connect_errno())
{
trigger_error('Fout bij verbinding: '.$mysqli->error);
}
$mysqli->autocommit(FALSE);
$mysqli->query("INSERT INTO tabel (naam) VALUES ('Piet')");
$mysqli->query("INSERT INTO tabel (naam) VALUES ('Karel')");
$mysqli->query("INSERT INTO tabel (naam) VALUES ('Kees')");
$mysqli->commit();
?>
Dit is de standaard manier waarop een transactie opgebouwd wordt. Allereerst zetten we met behulp van de autocommit() methode de waarde van autocommit op FALSE. Dit zorgt ervoor dat queries nog niet definities uitgevoerd worden in de database. Vervolgens voeren we de betreffende queries uit en gebruiken we de commit() methode om de aanpassingen definitief door te voeren.
Nu is dit echt het meest basale voorbeeld dat geen enkel voordeel heeft ten opzichte van het normaal uitvoeren van deze queries. Wat hebben we dan eigenlijk aan transacties en hoe kunnen we daar ons voordeel mee doen?
Allereerst kun je transacties gebruiken om een reeks queries ongedaan te maken zodra er een query niet correct uitgevoerd wordt.
Voorbeeld 15: Ongedaan maken van een reeks queries
<?php
$mysqli = new mysqli('host', 'user', 'password', 'database');
if(mysqli_connect_errno())
{
trigger_error('Fout bij verbinding: '.$mysqli->error);
}
// Queries definieren
$queries[] = "INSERT INTO tabel (naam) VALUES ('Piet')";
$queries[] = "INSERT INTO tabel (naam) VALUES ('Karel')";
$queries[] = "INSERT INTO tabel (naam) ('Kees')";
// Zet autocommit op FALSE
$mysqli->autocommit(FALSE);
// Voer de queries uit en controleer of ze gelukt zijn
foreach($queries as $query)
{
if(!$mysqli->query($query))
{
$errors[$query] = $mysqli->error;
}
}
// ROLLBACK of COMMIT
if(isset($errors))
{
$mysqli->rollback();
foreach($errors as $sql => $error)
{
echo '<pre>'.$error.' in SQL: '.$sql.'</pre>';
}
}
else
{
$mysqli->commit();
}
?>
De reeks queries die we achter elkaar willen uitvoeren zetten we in de array $queries. We zetten autocommit wederom op FALSE en gebruiken nu een foreach loop om de queries uit te voeren. Als er nu een query mislukt, wordt er een foutmelding toegevoegd aan de $errors array.
Door vervolgens te controleren of de $errors array bestaat, weten we direct of er fouten opgetreden zijn. Zo ja, dan gebruiken we de rollback() methode om alle queries ongedaan te maken en geven we de opgetreden fouten weer. Zijn er geen fouten opgetreden, dan gebruiken we de commit() methode om de aanpassingen definitief door te voeren.
In dit geval zal er niets in onze tabel veranderen omdat de laatste query zeker zal mislukken.
Voorbeeld 16: Werking ROLLBACK
<?php
$mysqli = new mysqli('host', 'user', 'password', 'database');
if(mysqli_connect_errno())
{
trigger_error('Fout bij verbinding: '.$mysqli->error);
}
$verwijder = "DELECT FROM klanten";
$selecteer = "SELECT COUNT(*) AS aantal FROM klanten";
// Zet autocommit op FALSE
$mysqli->autocommit(FALSE);
// Verwijder alle gegevens uit de klanten tabel
$mysqli->query($verwijder);
// Kijk hoeveel records er in de klanten tabel staan
$result = $mysqli->query($selecteer);
$row = $result->fetch_assoc();
echo 'Er staan '.$row['aantal'].' records in de klanten tabel <br>';
// ROLLBACK
$mysqli->rollback();
// Kijk wederom hoeveel records er in de klanten tabel staan
$result = $mysqli->query($selecteer);
$row = $result->fetch_assoc();
echo 'Er staan '.$row['aantal'].' records in de klanten tabel <br>';
?>
In dit scriptje laat ik zien wat de rollback() methode nou precies doet. Allereerst maar eens de output van het script:
Er staan 0 records in de klanten tabel
Er staan 3 records in de klanten tabel
Nadat we eerst alle records uit de klanten tabel verwijderd hebben, kijken we hoeveel records nog aanwezig zijn. Zoals het eerste resultaat ook aangeeft is dat er geen een meer. Echter na het uitvoeren van de rollback() methode staan er weer records in de klanten tabel. Het blijkt dus dat onze eerder uitgevoerde DELETE query ongedaan is gemaakt.
Let op dat ik dit script helemaal geen foutafhandeling toegepast heb. Normaal gesproken mag dat natuurlijk niet ontbreken!
Om het gebruik van transacties verder te verduidelijken, zal ik een voorbeeld uit de boeken geven. Dit voorbeeld betreft een geldtransactie tussen twee bankrekeningen van respectievelijk persoon A en B.
Het gaat hier om een overschrijving van 1000 euro van de rekening van persoon A naar die van persoon B. De voorwaarde waarop dit uitgevoerd kan worden is dat persoon A genoeg geld op zijn rekening heeft.
Voorbeeld 17: Overschrijving tussen twee rekeningen
<?php
$mysqli = new mysqli('host', 'user', 'password', 'database');
if(mysqli_connect_errno())
{
trigger_error('Fout bij verbinding: '.$mysqli->error);
}
// Queries
$queries[] = "UPDATE rekeningen SET saldo = saldo - 1000 WHERE klant = 'A'";
$queries[] = "UPDATE rekeningen SET saldo = saldo + 1000 WHERE klant = 'B'";
// Controle query
$controle = "SELECT saldo FROM rekeningen WHERE klant = 'A'";
// Zet autocommit op FALSE
$mysqli->autocommit(FALSE);
// Uitvoeren van queries en controleren of ze gelukt zijn
foreach($queries as $query)
{
if(!$result = $mysqli->query($query))
{
$errors[$query] = $mysqli->error;
}
if($mysqli->affected_rows == 0)
{
$errors[$query] = 'Er zijn geen rijen gewijzigd in SQL';
}
}
// Uitvoeren controle query en controleren waarde
if(!$result = $mysqli->query($controle))
{
$errors[$controle] = $mysqli->error;
}
else
{
$row = $result->fetch_assoc();
if($row['saldo'] < 0)
{
$errors[$controle] = 'Het saldo op een rekening is niet toereikend.';
}
}
// ROLLBACK of COMMIT
if(isset($errors))
{
$mysqli->rollback();
foreach($errors as $sql => $error)
{
echo '<pre>'.$error.' SQL: '.$sql.'</pre>';
}
}
else
{
$mysqli->commit();
}
?>
De UPDATE queries zorgen ervoor dat er 1000 van de rekening van persoon A gehaald wordt en bij het saldo van persoon B opgeteld wordt. De controle query haalt ter controle het nieuwe saldo persoon A op, dit mag immers niet negatief zijn.
Allereerst voeren we de update queries uit, kijken we of ze gelukt zijn en of er daadwerkelijk gegevens in de database aangepast zijn. Vervolgens voeren we de controle query uit en controleren we het saldo van persoon A.
Als er ergens in deze transactie fouten opgetreden zijn, draaien we alles terug met rollback() en geven we de foutmeldingen weer. Is het goed gegaan, dan maken we de overboeking definitief met de commit() methode.
Het gebruik van een transactie is hier een vereiste omdat het totale saldo in de tabel natuurlijk gelijk moet blijven. Er kan niet zomaar geld aangemaakt of vernietigd worden. Het grote voordeel is daarnaast dat tijdens de transactie het voor andere gebruikers niet mogelijk is om deze gegevens te wijzigen. Het kan dus nooit zo zijn dat twee gebruikers precies tegelijkertijd dezelfde gegevens wijzigen waardoor de data mogelijk corrupt kan raken.
Pagina 3
Proceduraal vs. Object georienteerd
Zoals ik in de inleiding al opmerkte, biedt de mysqli extensie ondersteuning voor zowel een procedurale als een object georienteerde interface.
In principe maakt het niets uit welke manier je gebruikt om met de database te communiceren, het is enkel een manier van programmeren. In deze tutorial zal ik voornamelijk gebruik maken van de object georienteerde manier maar omdat ik het procedurale gedeelte niet in zijn geheel over wil slaan, zal ik daar eerst aandacht aan besteden.
Procedurale interface
Het gebruik van de procedurale interface lijkt sterk op de oude manier van communiceren met de database. In plaats van de mysql_* functies, gebruik je nu echter de mysqli_* functies. De meeste functies zijn op een paar kleine dingetje na niet veranderd en de overstap zal dan ook niet erg lastig zijn.
Voorbeeld 1: Verbinding maken met de server
<?php
$link = mysqli_connect('host', 'user', 'password', 'database');
if(!$link)
{
trigger_error('Fout bij verbinden met database: '.mysqli_connect_error());
}
?>
Zoals je ziet wordt de mysqli_connect() functie op ongeveer dezelfde manier als de mysql_connect() functie gebruikt. Het enige verschil is dat de te selecteren database direct in de connect functie meegegeven worden. Het is nu dus niet meer nodig om een database te selecteren met mysqli_select_db().
Verder zien we in de foutafhandeling de functie mysqli_connect_error(). Voor het tonen van foutmeldingen veroorzaakt tijdens het maken van een verbinding gebruik je deze functie.
Voorbeeld 2: Selecteren van gegevens uit de database
<?php
$link = mysqli_connect('host', 'user', 'password', 'database');
if(!$link)
{
trigger_error('Fout bij verbinden met database: '.mysqli_connect_error());
}
$sql = "SELECT naam FROM tabel";
if(!$res = mysqli_query($link, $sql))
{
trigger_error('Fout in query: '.mysqli_error());
}
else
{
$aantal = mysqli_num_rows($res);
echo 'Aantal records: '.$aantal;
while($row = mysqli_fetch_assoc($res))
{
echo $row['naam'].'<br>';
}
}
?>
Ook hier lijkt de gebruikte syntax zeer veel op de oude manier.
Er is echter een belangrijk punt waar je rekening mee moet houden als je de procuderale methode gebruikt. Elke bewerking die je op de database uitvoert vereist nu namelijk een link-identifier om aan te geven om welke verbinding het gaat. Vroeger was deze parameter optioneel, nu is hij dus verplicht.
Let ook op de volgorde van de parameters van de mysqli_query() functie. Deze is precies tegengesteld aan die van mysql_query():
<?php
$res = mysqli_query($link, $sql);
$res = mysql_query($sql, $link);
?>
PHP zal natuurlijk vanzelf foutmeldingen genereren als je dit soort parameters verkeerd gebruikt.
Zoals ik al zei heeft bijna elke mysql_* functie een vergelijkbare mysqli_* functie. In principe zal er dus nog niet heel erg veel veranderen en zou je al prima uit de voeten moeten kunnen met de mysqli functies.
Object georienteerde interface
Voor de overzichtelijkheid van de tutorial zal ik nu alleen nog gebruik maken van de object georienteerde interface. Deze interface geniet mijn voorkeur aangezien je de mogelijkheid hebt om voor elke database verbinding een apart object aan te maken. Het voordeel hiervan is dat alle verschillende resultaten van een database verbinding als eigenschap van zo'n object beschikbaar zijn.
Voordat ik verder in ga op deze onderwerpen, zullen we eerst maar eens kijken naar het maken van een database verbinding en het uitvoeren van een simpel SELECT statement.
Voorbeeld 3: Verbinding maken met de server (2)
<?php
$mysqli = new mysqli('host', 'user', 'password', 'database');
if(mysqli_connect_errno())
{
trigger_error('Fout bij verbinding: '.$mysqli->error);
}
?>
We zien hier dat voor het maken van een database verbinding gebruik wordt gemaakt van de mysqli klasse die dezelfde parameters accepteert als de mysqli_connect() functie. Het voordeel is dat alle eigenschappen van deze verbinding, als eigenschap van het gecreeerde $mysqli object op te vragen zijn.
Het eerste voorbeeld daarvan is te zien in de foutafhandeling. Een eventuele foutmelding wordt opgehaald met $mysqli->error.
Voorbeeld 4: Selecteren van gegevens uit de database (2)
<?php
$mysqli = new mysqli('host', 'user', 'password', 'database');
if(mysqli_connect_errno())
{
trigger_error('Fout bij verbinding: '.$mysqli->error);
}
$sql = "SELECT naam FROM tabel";
if(!$result = $mysqli->query($sql))
{
trigger_error('Fout in query: '.$mysqli->error);
}
else
{
echo 'Aantal records: '.$result->num_rows;
while($row = $result->fetch_assoc())
{
echo $row['naam'].'<br>';
}
}
?>
Voor het uitvoeren van een simpele SELECT query zien we dat er gebruik wordt gemaakt van de query() methode. Het resultaat van deze methode is een object $result waarin de resultaat set van de query te vinden is. We zien dat we in dit geval geen $link mee hoeven te geven aan de query() methode. Dat komt omdat deze informatie een eigenschap is van het object $mysqli en PHP dus al weet om welke verbinding het gaat.
Vanaf dit punt kan het resultaat gefetched worden met bijvoorbeeld de fetch_assoc() methode. Dit zal je redelijk bekend voorkomen omdat het natuurlijk veel lijkt op de mysql_fetch_assoc() functie. Let erop dat de fetch_assoc() methode wel bij het object hoort dat de resultaat set bevat, in ons geval dus $result.
Om bijvoorbeeld het aantal rijen in een resultaat set op te halen, hoeven we nu geen functie meer te gebruiken. Deze waarde is namelijk een eigenschap van het $result object. Het aantal rijen kunnen we dus heel eenvoudig met $result->num_rows achterhalen.
In deze tutorial zal ik laten zien hoe je de belangrijkste methodes en eigenschappen gebruikt. In de php.net handleiding vind je alle beschikbare methodes en eigenschappen.
Opmerking
Voor lezers die nog niet veel kennis hebben van object georienteerd programmeren (OOP): Een methode is een functie van een bepaalde klasse, beschouw het als een gewone php functie. Een eigenschap is een zoals het wordt al zegt een eigenschap van een bepaalde klasse, beschouw het al een variabele.
Een methode wordt aangeroepen met $object->methode() en een eigenschap geef je als weer als $object->eigenschap. Let op het verschil in haakjes.
In principe maakt het niets uit welke manier je gebruikt om met de database te communiceren, het is enkel een manier van programmeren. In deze tutorial zal ik voornamelijk gebruik maken van de object georienteerde manier maar omdat ik het procedurale gedeelte niet in zijn geheel over wil slaan, zal ik daar eerst aandacht aan besteden.
Procedurale interface
Het gebruik van de procedurale interface lijkt sterk op de oude manier van communiceren met de database. In plaats van de mysql_* functies, gebruik je nu echter de mysqli_* functies. De meeste functies zijn op een paar kleine dingetje na niet veranderd en de overstap zal dan ook niet erg lastig zijn.
Voorbeeld 1: Verbinding maken met de server
<?php
$link = mysqli_connect('host', 'user', 'password', 'database');
if(!$link)
{
trigger_error('Fout bij verbinden met database: '.mysqli_connect_error());
}
?>
Zoals je ziet wordt de mysqli_connect() functie op ongeveer dezelfde manier als de mysql_connect() functie gebruikt. Het enige verschil is dat de te selecteren database direct in de connect functie meegegeven worden. Het is nu dus niet meer nodig om een database te selecteren met mysqli_select_db().
Verder zien we in de foutafhandeling de functie mysqli_connect_error(). Voor het tonen van foutmeldingen veroorzaakt tijdens het maken van een verbinding gebruik je deze functie.
Voorbeeld 2: Selecteren van gegevens uit de database
<?php
$link = mysqli_connect('host', 'user', 'password', 'database');
if(!$link)
{
trigger_error('Fout bij verbinden met database: '.mysqli_connect_error());
}
$sql = "SELECT naam FROM tabel";
if(!$res = mysqli_query($link, $sql))
{
trigger_error('Fout in query: '.mysqli_error());
}
else
{
$aantal = mysqli_num_rows($res);
echo 'Aantal records: '.$aantal;
while($row = mysqli_fetch_assoc($res))
{
echo $row['naam'].'<br>';
}
}
?>
Ook hier lijkt de gebruikte syntax zeer veel op de oude manier.
Er is echter een belangrijk punt waar je rekening mee moet houden als je de procuderale methode gebruikt. Elke bewerking die je op de database uitvoert vereist nu namelijk een link-identifier om aan te geven om welke verbinding het gaat. Vroeger was deze parameter optioneel, nu is hij dus verplicht.
Let ook op de volgorde van de parameters van de mysqli_query() functie. Deze is precies tegengesteld aan die van mysql_query():
<?php
$res = mysqli_query($link, $sql);
$res = mysql_query($sql, $link);
?>
PHP zal natuurlijk vanzelf foutmeldingen genereren als je dit soort parameters verkeerd gebruikt.
Zoals ik al zei heeft bijna elke mysql_* functie een vergelijkbare mysqli_* functie. In principe zal er dus nog niet heel erg veel veranderen en zou je al prima uit de voeten moeten kunnen met de mysqli functies.
Object georienteerde interface
Voor de overzichtelijkheid van de tutorial zal ik nu alleen nog gebruik maken van de object georienteerde interface. Deze interface geniet mijn voorkeur aangezien je de mogelijkheid hebt om voor elke database verbinding een apart object aan te maken. Het voordeel hiervan is dat alle verschillende resultaten van een database verbinding als eigenschap van zo'n object beschikbaar zijn.
Voordat ik verder in ga op deze onderwerpen, zullen we eerst maar eens kijken naar het maken van een database verbinding en het uitvoeren van een simpel SELECT statement.
Voorbeeld 3: Verbinding maken met de server (2)
<?php
$mysqli = new mysqli('host', 'user', 'password', 'database');
if(mysqli_connect_errno())
{
trigger_error('Fout bij verbinding: '.$mysqli->error);
}
?>
We zien hier dat voor het maken van een database verbinding gebruik wordt gemaakt van de mysqli klasse die dezelfde parameters accepteert als de mysqli_connect() functie. Het voordeel is dat alle eigenschappen van deze verbinding, als eigenschap van het gecreeerde $mysqli object op te vragen zijn.
Het eerste voorbeeld daarvan is te zien in de foutafhandeling. Een eventuele foutmelding wordt opgehaald met $mysqli->error.
Voorbeeld 4: Selecteren van gegevens uit de database (2)
<?php
$mysqli = new mysqli('host', 'user', 'password', 'database');
if(mysqli_connect_errno())
{
trigger_error('Fout bij verbinding: '.$mysqli->error);
}
$sql = "SELECT naam FROM tabel";
if(!$result = $mysqli->query($sql))
{
trigger_error('Fout in query: '.$mysqli->error);
}
else
{
echo 'Aantal records: '.$result->num_rows;
while($row = $result->fetch_assoc())
{
echo $row['naam'].'<br>';
}
}
?>
Voor het uitvoeren van een simpele SELECT query zien we dat er gebruik wordt gemaakt van de query() methode. Het resultaat van deze methode is een object $result waarin de resultaat set van de query te vinden is. We zien dat we in dit geval geen $link mee hoeven te geven aan de query() methode. Dat komt omdat deze informatie een eigenschap is van het object $mysqli en PHP dus al weet om welke verbinding het gaat.
Vanaf dit punt kan het resultaat gefetched worden met bijvoorbeeld de fetch_assoc() methode. Dit zal je redelijk bekend voorkomen omdat het natuurlijk veel lijkt op de mysql_fetch_assoc() functie. Let erop dat de fetch_assoc() methode wel bij het object hoort dat de resultaat set bevat, in ons geval dus $result.
Om bijvoorbeeld het aantal rijen in een resultaat set op te halen, hoeven we nu geen functie meer te gebruiken. Deze waarde is namelijk een eigenschap van het $result object. Het aantal rijen kunnen we dus heel eenvoudig met $result->num_rows achterhalen.
In deze tutorial zal ik laten zien hoe je de belangrijkste methodes en eigenschappen gebruikt. In de php.net handleiding vind je alle beschikbare methodes en eigenschappen.
Opmerking
Voor lezers die nog niet veel kennis hebben van object georienteerd programmeren (OOP): Een methode is een functie van een bepaalde klasse, beschouw het als een gewone php functie. Een eigenschap is een zoals het wordt al zegt een eigenschap van een bepaalde klasse, beschouw het al een variabele.
Een methode wordt aangeroepen met $object->methode() en een eigenschap geef je als weer als $object->eigenschap. Let op het verschil in haakjes.
Pagina 4
Uitbreiden van de mysqli klasse
Dit hoofdstuk gaat een stuk dieper in op de OOP functionaliteit van de mysqli extensie. Voor dit hoofdstuk is in enige kennis van object georienteerd programmeren een vereiste.
De functionaliteit van de object georienteerde (OO) interface wordt benaderd via de mysqli, mysqli_stmt en mysqli_result klasses. De mysqli klasse representeert een database verbinding, de mysqli_stmt klasse een prepared statement en de mysqli_result klasse een resultaat set van een query.
Extenden van de mysqli klasse
Het leuke is nu dat je deze klasses gewoon kunt extenden met een door jezelf geschreven klasse. Dit geldt voor alle drie de klassen maar in deze tutorial zal ik me beperken tot het extenden van de mysqli klasse.
Voorbeeld 18: Extenden van de mysqli klasse
<?php
// Een child van de mysqli klasse aanmaken.
class extended_mysqli extends mysqli
{
function query_and_fetch($query)
{
$result = $this->query($query);
return $result->fetch_row();
}
}
$mysqli = new extended_mysqli('host', 'user', 'pass', 'database');
$sql = "SELECT email FROM tabel WHERE naam = 'Kees'";
$row = $mysqli->query_and_fetch($sql);
echo $row['email']; // Output: [email protected]
?>
Hier hebben we onze eigenlijk klasse extended_mysqli geschreven. Deze klasse is een child van de mysqli klasse, we hebben dus beschikking over alle eigenschappen en methodes die de mysqli klasse ook heeft. In onze klasse hebben we een nieuwe methode genaamd query_and_fetch() aangemaakt die twee reeds bestaande methoden combineert.
Voor het opzetten van een nieuwe verbinding gebruiken we nu natuurlijk onze eigen klasse. Vervolgens voeren we een query uit met de nieuwe methode en het resultaat is direct duidelijk.
Dit is maar een heel eenvoudig voorbeeldje en alle foutafhandeling ontbreekt. Natuurlijk moet deze nog wel toegevoegd worden!
Foutafhandeling met de Exeption klasse
In plaats van in onze scripts telkens te moeten controleren of er een fout opgetreden is bij het uitvoeren van een query, kunnen we dit ook op een elegantere manier aanpakken. Hierbij maken we gebruik van de Exeption klasse.
Voorbeeld 19: Foutafhandeling met de Exception klasse
<?php
// Een child van de mysqli klaasse aanmaken.
class extended_mysqli extends mysqli
{
function query($query)
{
$result = parent::query($query)
if($this->error)
{
throw new Exception(mysqli_error($this), mysqli_errno($this));
}
return $result;
}
}
$mysqli = new extended_mysqli('host', 'user', 'pass', 'database');
$sql = "SELECT email FROM tabel WHERE naam = 'Kees'";
try {
$result = $mysqli->query($sql);
var_dump($result->fetch_assoc());
}
catch(Exeption $e)
{
var_dump($e->getTrace());
}
?>
Aangezien we de Exception klasse willen gebruiken om fouten bij het uitvoeren van een query() af te vangen, zullen we een eigen query() methode in onze klasse op moeten nemen. Binnen deze query() methode kunnen we de foutafhandeling dan bepalen.
Met parent::query() roepen we de query() methode uit de mysqli klasse aan. Vervolgens controleren we of $this->error bestaat en er dus een fout opgetreden is. Zo ja, dan gooien we er een Exception tegenaan. In de rest van het script maken we gebruik van de try/catch combinatie om deze exceptions af te vangen.
Voor meer informatie en enkele andere voorbeelden over het uitbreiden van de mysqli klasse kijk je eens naar deze tutorial op zend.com.
De functionaliteit van de object georienteerde (OO) interface wordt benaderd via de mysqli, mysqli_stmt en mysqli_result klasses. De mysqli klasse representeert een database verbinding, de mysqli_stmt klasse een prepared statement en de mysqli_result klasse een resultaat set van een query.
Extenden van de mysqli klasse
Het leuke is nu dat je deze klasses gewoon kunt extenden met een door jezelf geschreven klasse. Dit geldt voor alle drie de klassen maar in deze tutorial zal ik me beperken tot het extenden van de mysqli klasse.
Voorbeeld 18: Extenden van de mysqli klasse
<?php
// Een child van de mysqli klasse aanmaken.
class extended_mysqli extends mysqli
{
function query_and_fetch($query)
{
$result = $this->query($query);
return $result->fetch_row();
}
}
$mysqli = new extended_mysqli('host', 'user', 'pass', 'database');
$sql = "SELECT email FROM tabel WHERE naam = 'Kees'";
$row = $mysqli->query_and_fetch($sql);
echo $row['email']; // Output: [email protected]
?>
Hier hebben we onze eigenlijk klasse extended_mysqli geschreven. Deze klasse is een child van de mysqli klasse, we hebben dus beschikking over alle eigenschappen en methodes die de mysqli klasse ook heeft. In onze klasse hebben we een nieuwe methode genaamd query_and_fetch() aangemaakt die twee reeds bestaande methoden combineert.
Voor het opzetten van een nieuwe verbinding gebruiken we nu natuurlijk onze eigen klasse. Vervolgens voeren we een query uit met de nieuwe methode en het resultaat is direct duidelijk.
Dit is maar een heel eenvoudig voorbeeldje en alle foutafhandeling ontbreekt. Natuurlijk moet deze nog wel toegevoegd worden!
Foutafhandeling met de Exeption klasse
In plaats van in onze scripts telkens te moeten controleren of er een fout opgetreden is bij het uitvoeren van een query, kunnen we dit ook op een elegantere manier aanpakken. Hierbij maken we gebruik van de Exeption klasse.
Voorbeeld 19: Foutafhandeling met de Exception klasse
<?php
// Een child van de mysqli klaasse aanmaken.
class extended_mysqli extends mysqli
{
function query($query)
{
$result = parent::query($query)
if($this->error)
{
throw new Exception(mysqli_error($this), mysqli_errno($this));
}
return $result;
}
}
$mysqli = new extended_mysqli('host', 'user', 'pass', 'database');
$sql = "SELECT email FROM tabel WHERE naam = 'Kees'";
try {
$result = $mysqli->query($sql);
var_dump($result->fetch_assoc());
}
catch(Exeption $e)
{
var_dump($e->getTrace());
}
?>
Aangezien we de Exception klasse willen gebruiken om fouten bij het uitvoeren van een query() af te vangen, zullen we een eigen query() methode in onze klasse op moeten nemen. Binnen deze query() methode kunnen we de foutafhandeling dan bepalen.
Met parent::query() roepen we de query() methode uit de mysqli klasse aan. Vervolgens controleren we of $this->error bestaat en er dus een fout opgetreden is. Zo ja, dan gooien we er een Exception tegenaan. In de rest van het script maken we gebruik van de try/catch combinatie om deze exceptions af te vangen.
Voor meer informatie en enkele andere voorbeelden over het uitbreiden van de mysqli klasse kijk je eens naar deze tutorial op zend.com.
Pagina 5
Object georienteerde interface van mysqli
Op de vorige pagina heb ik al een kleine inleiding gegeven in het gebruik van de object georienteerde interface van de mysqli extensie. Hier zal ik nog enkele voorbeelden geven van veel voorkomende queries geven om de manier waarop een query uitgevoerd wordt te verduidelijken.
Voorbeeld 5: Een INSERT query
<?php
$mysqli = new mysqli('host', 'user', 'password', 'database');
if(mysqli_connect_errno())
{
trigger_error('Fout bij verbinding: '.$mysqli->error);
}
// Controleren en beveiligen van variabelen
$naam = $mysqli->real_escape_string($_POST['naam'])
$sql = "
INSERT INTO tabel (
naam,
datum )
VALUES (
'".$naam."',
NOW()
)";
if(!$result = $mysqli->query($sql))
{
trigger_error('Fout in query: '.$mysqli->error);
}
else
{
echo 'Het invoegen is gelukt.';
}
?>
Dit scriptje is ongeveer hetzelfde als dat op de vorige pagina. Nu weten we natuurlijk dat we input van een gebruiker altijd moeten beveiligen en vroeger gebruikten we dan ook de functie mysql_real_escape_string() voor dat doeleinde. Nu kunnen we daar de real_escape_string() methode van het $mysqli object voor gebruiken.
Het uitvoeren van de query gaat op precies dezelfde manier als op de vorige pagina.
Voorbeeld 6: Een UPDATE query
<?php
$mysqli = new mysqli('host', 'user', 'password', 'database');
if(mysqli_connect_errno())
{
trigger_error('Fout bij verbinding: '.$mysqli->error);
}
// Controleren en beveiligen van variabelen
$naam = $mysqli->real_escape_string($_POST['naam'])
$sql = "
UPDATE tabel
SET naam = '".$naam."'
WHERE id = 10
";
if(!$result = $mysqli->query($sql))
{
trigger_error('Fout in query: '.$mysqli->error);
}
else
{
if($mysqli->affected_rows > 0)
{
echo 'Het updaten is gelukt';
}
}
?>
Ook het uitvoeren van een UPDATE query doe je op precies dezelfde manier. Nu weten we dat we na een UPDATE of DELETE query altijd moeten controleren of er wel iets in de database veranderd is. Waar we vroeger mysql_affected_rows() gebruiken kunnen we nu de affected_rows eigenschap van het $mysqli object gebruiken. Deze eigenschap hoort bij het $mysqli object omdat het een eigenschap van een verbinding is.
Dit in tegenstelling tot de num_rows eigenschap dat een eigenschap van het mysqli_result object, aangeduid met $result, is. Immers het aantal rijen in een result set, is een eigenschap van die result set.
Op deze manier kun je allerlei soorten queries uitvoeren, resultaten fetchen en gegevens controleren. In dit opzicht is er niet veel veranderd ten opzichte van de mysql extensie.
Voorbeeld 5: Een INSERT query
<?php
$mysqli = new mysqli('host', 'user', 'password', 'database');
if(mysqli_connect_errno())
{
trigger_error('Fout bij verbinding: '.$mysqli->error);
}
// Controleren en beveiligen van variabelen
$naam = $mysqli->real_escape_string($_POST['naam'])
$sql = "
INSERT INTO tabel (
naam,
datum )
VALUES (
'".$naam."',
NOW()
)";
if(!$result = $mysqli->query($sql))
{
trigger_error('Fout in query: '.$mysqli->error);
}
else
{
echo 'Het invoegen is gelukt.';
}
?>
Dit scriptje is ongeveer hetzelfde als dat op de vorige pagina. Nu weten we natuurlijk dat we input van een gebruiker altijd moeten beveiligen en vroeger gebruikten we dan ook de functie mysql_real_escape_string() voor dat doeleinde. Nu kunnen we daar de real_escape_string() methode van het $mysqli object voor gebruiken.
Het uitvoeren van de query gaat op precies dezelfde manier als op de vorige pagina.
Voorbeeld 6: Een UPDATE query
<?php
$mysqli = new mysqli('host', 'user', 'password', 'database');
if(mysqli_connect_errno())
{
trigger_error('Fout bij verbinding: '.$mysqli->error);
}
// Controleren en beveiligen van variabelen
$naam = $mysqli->real_escape_string($_POST['naam'])
$sql = "
UPDATE tabel
SET naam = '".$naam."'
WHERE id = 10
";
if(!$result = $mysqli->query($sql))
{
trigger_error('Fout in query: '.$mysqli->error);
}
else
{
if($mysqli->affected_rows > 0)
{
echo 'Het updaten is gelukt';
}
}
?>
Ook het uitvoeren van een UPDATE query doe je op precies dezelfde manier. Nu weten we dat we na een UPDATE of DELETE query altijd moeten controleren of er wel iets in de database veranderd is. Waar we vroeger mysql_affected_rows() gebruiken kunnen we nu de affected_rows eigenschap van het $mysqli object gebruiken. Deze eigenschap hoort bij het $mysqli object omdat het een eigenschap van een verbinding is.
Dit in tegenstelling tot de num_rows eigenschap dat een eigenschap van het mysqli_result object, aangeduid met $result, is. Immers het aantal rijen in een result set, is een eigenschap van die result set.
Op deze manier kun je allerlei soorten queries uitvoeren, resultaten fetchen en gegevens controleren. In dit opzicht is er niet veel veranderd ten opzichte van de mysql extensie.
Pagina 6
Slotwoord en referenties
In deze tutorial heb ik geprobeerd om een uitgebreid overzicht te geven van de mogelijkheden die de mysqli extensie bieden. Natuurlijk heb ik lang niet alle aspecten van deze extensie kunnen behandelen, ik heb me hier beperkt tot de meest gebruikte toepassingen. Mocht je je verder willen verdiepen, kijk dan eens verder op onderstaande links.
In deze tutorial ben ik, zoals in het begin al vermeld, expres niet ingegaan op het procedurale gebruik van de mysqli extensie. Mocht er veel vraag naar zijn, dan zal ik wellicht in de toekomst deze tutorial nog eens uitbreiden en stukken procedurale code erin opnemen.
Verder zou ik iedereen willen aanraden om geleidelijk aan over te stappen op het gebruik van de mysqli extensie. Niet alleen omdat dit de extensie van de toekomst is, maar vooral omdat het je een aantal belangrijke nieuwe functies biedt. Deze nieuwe functionaliteit kan de performace van je website en de overzichtelijkheid van je code zeker ten goede komen. Bovendien is het mogelijk om deze extensie geheel naar je eigen wensen aan te passen, iets dat met de mysql extensie niet kon.
Reacties, opmerkingen en/of gevonden fouten zijn natuurlijk altijd welkom!
Deze tutorial is ook hier te vinden.
Bronnen
[li]Performing basic tasks with MySQL 4.1 and above, using mysqli with PHP 5[/li]
[li]Implementing commit() and rollback() with mysqli and PHP 5[/li]
[li]Implementing additional methods with mysqli and PHP 5[/li]
[li]ext/mysqli: Overview and Prepared statements[/li]
[li]ext/mysqli: Extending mysqli[/li]
[li]PHP.net Handleiding[/li]
In deze tutorial ben ik, zoals in het begin al vermeld, expres niet ingegaan op het procedurale gebruik van de mysqli extensie. Mocht er veel vraag naar zijn, dan zal ik wellicht in de toekomst deze tutorial nog eens uitbreiden en stukken procedurale code erin opnemen.
Verder zou ik iedereen willen aanraden om geleidelijk aan over te stappen op het gebruik van de mysqli extensie. Niet alleen omdat dit de extensie van de toekomst is, maar vooral omdat het je een aantal belangrijke nieuwe functies biedt. Deze nieuwe functionaliteit kan de performace van je website en de overzichtelijkheid van je code zeker ten goede komen. Bovendien is het mogelijk om deze extensie geheel naar je eigen wensen aan te passen, iets dat met de mysql extensie niet kon.
Reacties, opmerkingen en/of gevonden fouten zijn natuurlijk altijd welkom!
Deze tutorial is ook hier te vinden.
Bronnen
[li]Performing basic tasks with MySQL 4.1 and above, using mysqli with PHP 5[/li]
[li]Implementing commit() and rollback() with mysqli and PHP 5[/li]
[li]Implementing additional methods with mysqli and PHP 5[/li]
[li]ext/mysqli: Overview and Prepared statements[/li]
[li]ext/mysqli: Extending mysqli[/li]
[li]PHP.net Handleiding[/li]
Pagina 7
Meerdere queries tegelijk uitvoeren
Het zal vast wel eens voorgekomen zijn dat je in een script op een punt komt waar je meerdere queries moet uitvoeren. Een van de nieuwe features die beschikbaar zijn in de mysqli extensie, is de mogelijkheid om meerdere queries tegelijkertijd uit te voeren. Met tegelijkertijd bedoel ik dan het uitvoeren van de queries in 1 stap oftewel door maar 1 keer de query() methode te gebruiken.
Voorbeeld 8: Het uitvoeren van meerdere queries tegelijk
<?php
$mysqli = new mysqli('host', 'user', 'password', 'database');
if(mysqli_connect_errno())
{
trigger_error('Fout bij verbinding: '.$mysqli->error);
}
$sql = "
INSERT INTO gegevens (naam, email)
VALUES ('Piet', '[email protected]')
;
UPDATE inserts
SET last_insert = NOW()
WHERE naam = 'Piet'
";
if(!$mysqli->multi_query($sql))
{
trigger_error('Fout in query: '.$mysqli->error);
}
else
{
do
{
if($mysqli->affected_rows > 0)
{
echo 'Query gelukt <br>';
}
}
while($mysqli->next_result());
}
?>
Allereerst hebben we hier twee queries samengevoegd door ze te scheiden met een ;. Vervolgens gebruiken we de multi_query() methode om deze queries uit te voeren. Als blijkt dat die queries gelukt zijn, gebruiken we een do/while loop voor het controleren van de resultaten.
Het gebruik van deze methode is een beetje tricky aangezien de controle van de queries nogal lastig gaat. In dit geval controleren we de waarde van de affected_rows eigenschap in de do/while loop om te zien of er iets in de database aangepast is. Met de next_result() methode zorgen we dat het resultaat van de volgende query gecontroleerd wordt. Het lastige van dit hele verhaal is dat je de queries niet afzonderlijk kunt controleren, het do gedeelte van de loop verandert namelijk niet en wordt toegepast op het resultaat van ieder query.
In het volgende voorbeeld zal dat duidelijker worden.
Voorbeeld 9: Meerdere SELECT queries
<?php
$mysqli = new mysqli('host', 'user', 'password', 'database');
if(mysqli_connect_errno())
{
trigger_error('Fout bij verbinding: '.$mysqli->error);
}
$sql = "SELECT naam, email FROM tabel; SELECT naam FROM tabel";
if(!$mysqli->multi_query($sql))
{
trigger_error('Fout in query: '.$mysqli->error);
}
else
{
do
{
if($result = $mysqli->store_result())
{
while($row = $result->fetch_assoc())
{
echo $row['naam'].'-'.$row['email'].'<br>';
}
}
if($mysqli->more_results())
{
echo 'Resultaat van volgende query:<br>';
}
}while($mysqli->next_result());
}
?>
Het verschil met het vorige voorbeeld is dat we nu te maken hebben met een resultaat set waar we gegevens uit willen halen. Daartoe gebruiken we de methode store_result() om beschikking te krijgen over een mysqli_result object. Vervolgens kunnen we met de fetch_assoc() methode de resultaten fetchen en daarna weergeven.
De more_results() methode retourneert TRUE als er nog meer resultaat sets zijn die verwerkt kunnen worden. Om de volgende resultaat set te laden gebruiken we de next_result() methode.
Het probleem waar ik het al over had zit hem dus in het do-gedeelte van de loop. Dat gedeelte verandert niet en wordt dus toegepast op het resultaat van elke query. In dit geval zal de tweede query dus een probleem opleveren aangezien daar geen veld 'email' opgehaald wordt. Het script zal dus een aantal notices geven aangezien de variabele $row['email'] niet zal bestaan.
Let dus goed op als je deze methode gebruikt om meerdere queries uit te voeren. Ik zou aanraden om dit alleen te gebruiken voor bijvoorbeeld INSERT, UPDATE of DELETE queries. Daarvan kun je immers met eenzelfde do-statement controleren of een query gelukt is. Deze methode is minder geschikt voor het uitvoeren van meerdere SELECT queries, iets dat met een goed datamodel bovendien bijna niet voor zal komen.
Voorbeeld 8: Het uitvoeren van meerdere queries tegelijk
<?php
$mysqli = new mysqli('host', 'user', 'password', 'database');
if(mysqli_connect_errno())
{
trigger_error('Fout bij verbinding: '.$mysqli->error);
}
$sql = "
INSERT INTO gegevens (naam, email)
VALUES ('Piet', '[email protected]')
;
UPDATE inserts
SET last_insert = NOW()
WHERE naam = 'Piet'
";
if(!$mysqli->multi_query($sql))
{
trigger_error('Fout in query: '.$mysqli->error);
}
else
{
do
{
if($mysqli->affected_rows > 0)
{
echo 'Query gelukt <br>';
}
}
while($mysqli->next_result());
}
?>
Allereerst hebben we hier twee queries samengevoegd door ze te scheiden met een ;. Vervolgens gebruiken we de multi_query() methode om deze queries uit te voeren. Als blijkt dat die queries gelukt zijn, gebruiken we een do/while loop voor het controleren van de resultaten.
Het gebruik van deze methode is een beetje tricky aangezien de controle van de queries nogal lastig gaat. In dit geval controleren we de waarde van de affected_rows eigenschap in de do/while loop om te zien of er iets in de database aangepast is. Met de next_result() methode zorgen we dat het resultaat van de volgende query gecontroleerd wordt. Het lastige van dit hele verhaal is dat je de queries niet afzonderlijk kunt controleren, het do gedeelte van de loop verandert namelijk niet en wordt toegepast op het resultaat van ieder query.
In het volgende voorbeeld zal dat duidelijker worden.
Voorbeeld 9: Meerdere SELECT queries
<?php
$mysqli = new mysqli('host', 'user', 'password', 'database');
if(mysqli_connect_errno())
{
trigger_error('Fout bij verbinding: '.$mysqli->error);
}
$sql = "SELECT naam, email FROM tabel; SELECT naam FROM tabel";
if(!$mysqli->multi_query($sql))
{
trigger_error('Fout in query: '.$mysqli->error);
}
else
{
do
{
if($result = $mysqli->store_result())
{
while($row = $result->fetch_assoc())
{
echo $row['naam'].'-'.$row['email'].'<br>';
}
}
if($mysqli->more_results())
{
echo 'Resultaat van volgende query:<br>';
}
}while($mysqli->next_result());
}
?>
Het verschil met het vorige voorbeeld is dat we nu te maken hebben met een resultaat set waar we gegevens uit willen halen. Daartoe gebruiken we de methode store_result() om beschikking te krijgen over een mysqli_result object. Vervolgens kunnen we met de fetch_assoc() methode de resultaten fetchen en daarna weergeven.
De more_results() methode retourneert TRUE als er nog meer resultaat sets zijn die verwerkt kunnen worden. Om de volgende resultaat set te laden gebruiken we de next_result() methode.
Het probleem waar ik het al over had zit hem dus in het do-gedeelte van de loop. Dat gedeelte verandert niet en wordt dus toegepast op het resultaat van elke query. In dit geval zal de tweede query dus een probleem opleveren aangezien daar geen veld 'email' opgehaald wordt. Het script zal dus een aantal notices geven aangezien de variabele $row['email'] niet zal bestaan.
Let dus goed op als je deze methode gebruikt om meerdere queries uit te voeren. Ik zou aanraden om dit alleen te gebruiken voor bijvoorbeeld INSERT, UPDATE of DELETE queries. Daarvan kun je immers met eenzelfde do-statement controleren of een query gelukt is. Deze methode is minder geschikt voor het uitvoeren van meerdere SELECT queries, iets dat met een goed datamodel bovendien bijna niet voor zal komen.
Pagina 8
Prepared statements
Een andere nieuwe feature die de mysqli extensie beschikbaar stelt, is het gebruik van prepared statements bij het uitvoeren sql queries. Deze prepared statements bieden de programmeur de mogelijkheid tot het creeren van queries die veiliger zijn, waarvan de performance beter is en die eenvoudiger te noteren zijn. Het grote voordeel van prepared statements is dat een bepaalde query op een efficiente manier vele malen achter elkaar uitgevoerd kan worden.
Er zijn twee soorten prepared statements:
[li]Bound result prepared statements - Gebruikt voor SELECT[/li]
[li]Bound parameter prepared statements - Gebruikt voor INSERT, UPDATE en DELETE[/li]
Bound Parameters
Bound parameter prepared statements bieden de mogelijkheid om templates van queries op te slaan op de MySQL server. Als de query uitgevoerd moet worden, worden de gegevens die in de template ingevuld moeten worden naar de database server gestuurd. Een complete query wordt gevormd en uitgevoerd.
Het proces van maken en gebruiken van bound parameter prepared statements is vrij eenvoudig en gaat als volgt.
Allereerst wordt er een query template geschreven en naar de MySQL server gestuurd. Deze ontvangt de template, controleert de syntax, voert hem uit om te kijken of hij logisch is en slaat hem vervolgens op in een speciale buffer. Vervolgens stuurt de server een speciale variabele terug waarmee later naar het statement gerefereerd kan worden.
Als een query uitgevoerd moet worden, wordt met behulp van deze variabele de in de query in te vullen gegevens naar de database gestuurd. Een query wordt gevormd en uitgevoerd.
Deze methode heeft een aantal belangrijke voordelen:
De body van de query hoeft maar een keer naar de server verzonden te worden. Bij het uitvoeren van de query worden alleen de in te vullen gegevens naar de server gestuurd. Het meeste werkt bestaande uit valideren en parsen van de query hoeft dus ook maar een keer uitgevoerd te worden.
De data die naar server verstuurd wordt, hoeft niet door een functie als mysqli_real_escape_string() gehaald te worden. In plaats daarvan werken de MySQL client en server samen om de verstuurde data veilig te verwerken zodra het gecombineerd wordt met het prepared statement.
Voorbeeld 10: Bound parameter prepared statement
<?php
$mysqli = new mysqli('host', 'user', 'password', 'database');
if(mysqli_connect_errno())
{
trigger_error('Fout bij verbinding: '.$mysqli->error);
}
$sql = "
INSERT INTO tabel (naam, email, leeftijd, datum)
VALUES (?, ?, ?, NOW())";
if($stmt = $mysqli->prepare($sql))
{
$stmt->bind_param('ssi', $naam, $email, $leeftijd);
$naam = 'Piet';
$email = '[email protected]';
$leeftijd = '34';
if(!$stmt->execute())
{
echo 'Het uitvoeren van de query is mislukt: '.$stmt->error.' in query: '.$sql;
}
$naam = 'Kees';
$email = '[email protected]';
$leeftijd = '40';
if(!$stmt->execute())
{
echo 'Het uitvoeren van de query is mislukt: '.$stmt->error.' in query: '.$sql;
}
$naam = 'Karel';
$email = '[email protected]';
$leeftijd = '25';
if(!$stmt->execute())
{
echo 'Het uitvoeren van de query is mislukt: '.$stmt->error.' in query: '.$sql;
}
$stmt->close();
}
else
{
echo 'Er zit een fout in de query: '.$mysqli->error;
}
?>
In dit script zien we weer een aantal nieuwe dingen, dus laten we er maar eens stap voor stap doorheen lopen.
Zoals elk script beginnen we natuurlijk weer met het maken van een database verbinding, dat moet nu toch wel al vrij vertrouwd zijn.
Daarna declareren we de SQL query die we gaan gebruiken, of beter gezegd: de template van de query. De template bestaat uit de complete query zonder de gegevens die telkens veranderen. We gebruiken zogenaamde placeholders (?) om aan te geven waar in de query variabele gegevens komen te staan.
De volgende stap is het gebruik van de bind_param() methode. Met deze methode geven we aan van wat voor type de in te voegen variabelen zijn. Als eerste parameter van deze variabele is een string vereist waarmee we het type van de variabelen vastleggen.
Elk teken uit die string komt overeen met een placeholder uit de query template en een extra parameter uit de bind_param() methode. Hierbij kan gebruik gemaakt worden van de volgende tekens die de volgende types aanduiden:
[li]s - De variabele is een string[/li]
[li]i - De variabele is een integer[/li]
[li]d - De variabele is een double of een float[/li]
[li]b - De variabele is een blob[/li]
In bovenstaand voorbeeld houdt 'ssi' in dat de eerste twee variabelen $naam en $email als strings behandeld worden en de variabele $leeftijd als integer. Let erop de de volgorde van genoemde variabelen overeenkomt met de positie van de placeholders in de template.
Let er ook op dat voor elke letter in de eerste parameter van bind_param() er een variabele als paramter meegegeven wordt:
<?php
$stmt->bind_param('s', $string);
$stmt->bind_param('si', $string, $int);
$stmt->bind_param('sid', $string, $int, $float);
?>
In het script worden vervolgens waarden toegekend aan de variabelen en wordt de query uitgevoert met de execute() methode. Vervolgens is het een kwestie van het opnieuw definieren van de variabelen en wederom het aanroepen van de execute() methode. Op deze manier wordt steeds dezelfde INSERT query met verschillende waarden uitgevoerd.
Voorbeeld 11: Een efficientere manier van gegevens verwerken
<?php
$mysqli = new mysqli('host', 'user', 'password', 'database');
if(mysqli_connect_errno())
{
trigger_error('Fout bij verbinding: '.$mysqli->error);
}
$personen = array(
array(
'naam' => 'Piet',
'email' => '[email protected]',
'leeftijd' => 34 ),
array(
'naam' => 'Kees',
'email' => '[email protected]',
'leeftijd' => 40 ),
array(
'naam' => 'Karel',
'email' => '[email protected]',
'leeftijd' => 25 )
);
$sql = "
INSERT INTO tabel (naam, email, leeftijd, datum)
VALUES (?, ?, ?, NOW())";
if($stmt = $mysqli->prepare($sql))
{
$stmt->bind_param('ssi', $naam, $email, $leeftijd);
foreach($personen as $persoon)
{
$naam = $persoon['naam'];
$email = $persoon['email'];
$leeftijd = $persoon['leeftijd'];
if(!$stmt->execute())
{
echo 'Het uitvoeren van de query is mislukt: '.$stmt->error.' in query: '.$sql;
}
}
$stmt->close();
}
else
{
echo 'Er zit een fout in de query: '.$mysqli->error;
}
?>
Dit voorbeeld laat zien dat je gegevens ook uit bijvoorbeeld een array kunt halen. Als je er maar te allen tijde voor zorgt dat de variabelen die voorkomen in de bind_param() methode bestaan en van het juiste type zijn.
Bound Results
De methode voor de bound result prepared statements is bijna hetzelfde als die voor de bound parameter prepared statements. Het enige verschil is dat we nu te maken hebben met gegevens die als resultaat uit een database query komen.
Het stappenplan is als volgt:
[li]Maak een query[/li]
[li]Vraag de MySQL server om de query voor te bereiden[/li]
[li]Koppel PHP variabelen aan kolommen uit de query[/li]
[li]Vraag de MySQL server om de query uit te voeren[/li]
[li]Zorg dat een nieuwe rij met gegevens in de gekoppelde variabelen geladen wordt[/li]
Voorbeeld 12: Bound result prepared statement
<?php
$mysqli = new mysqli('host', 'user', 'password', 'database');
if(mysqli_connect_errno())
{
trigger_error('Fout bij verbinding: '.$mysqli->error);
}
$sql = "
SELECT naam, email, leeftijd
FROM tabel
ORDER BY leeftijd DESC ";
if($stmt = $mysqli->prepare($sql))
{
if(!$stmt->execute())
{
echo 'Het uitvoeren van de query is mislukt: '.$stmt->error.' in query: '.$sql;
}
else
{
$stmt->bind_result($naam, $email, $leeftijd);
while($stmt->fetch())
{
echo $naam.'-'.$leeftijd.'-'.$email.'<br>';
}
}
$stmt->close();
}
else
{
echo 'Er zit een fout in de query: '.$mysqli->error;
}
?>
Met de methode bind_result() is het dus mogelijk om variabelen te koppelen aan de kolomnamen (of indien gebruikt aliassen). Door de fetch() methode in een while loop te plaatsen wordt er door alle rijen uit de resultaat set gelopen en kunnen de gegevens weergegeven worden.
Dit script zal iets opleveren als:
Voorbeeld 13: Een combinatie van bound paramters en bound results
<?php
$mysqli = new mysqli('host', 'user', 'password', 'database');
if(mysqli_connect_errno())
{
trigger_error('Fout bij verbinding: '.$mysqli->error);
}
$sql = "
SELECT naam, leeftijd
FROM tabel
WHERE naam LIKE ?
ORDER BY naam";
if($stmt = $mysqli->prepare($sql))
{
$stmt->bind_param('s', $zoek);
$zoek = 'K%';
if(!$stmt->execute())
{
echo 'Het uitvoeren van de query is mislukt: '.$stmt->error.' in query: '.$sql;
}
else
{
$stmt->bind_result($naam, $leeftijd);
while($stmt->fetch())
{
echo $naam.'-'.$leeftijd.'<br>';
}
}
$stmt->close();
}
else
{
echo 'Er zit een fout in de query: '.$mysqli->error;
}
?>
Hier zien we een combinatie van de twee voorgaande voorbeelden. Allereerst gebruiken we een query template en vragen om die voor te bereiden. Vervolgens koppelen we de benodigde variabelen en laten we het statement uitvoeren.
Daarna gebruiken we de bind_result() methode om de resultaten te koppelen aan variabelen en geven we deze variabelen weer na fetchen van de resultaat set.
Dit scriptje laat duidelijk zien dat de placeholders in de query template ook andere dingen kunnen bevatten dan kolomnamen. Dit gaat allemaal goed, zolang je er maar voor zorgt dat de juiste variabelen aan de query gekoppeld worden en dat deze variabelen de juiste gegevens bevatten.
Er zijn twee soorten prepared statements:
[li]Bound result prepared statements - Gebruikt voor SELECT[/li]
[li]Bound parameter prepared statements - Gebruikt voor INSERT, UPDATE en DELETE[/li]
Bound Parameters
Bound parameter prepared statements bieden de mogelijkheid om templates van queries op te slaan op de MySQL server. Als de query uitgevoerd moet worden, worden de gegevens die in de template ingevuld moeten worden naar de database server gestuurd. Een complete query wordt gevormd en uitgevoerd.
Het proces van maken en gebruiken van bound parameter prepared statements is vrij eenvoudig en gaat als volgt.
Allereerst wordt er een query template geschreven en naar de MySQL server gestuurd. Deze ontvangt de template, controleert de syntax, voert hem uit om te kijken of hij logisch is en slaat hem vervolgens op in een speciale buffer. Vervolgens stuurt de server een speciale variabele terug waarmee later naar het statement gerefereerd kan worden.
Als een query uitgevoerd moet worden, wordt met behulp van deze variabele de in de query in te vullen gegevens naar de database gestuurd. Een query wordt gevormd en uitgevoerd.
Deze methode heeft een aantal belangrijke voordelen:
De body van de query hoeft maar een keer naar de server verzonden te worden. Bij het uitvoeren van de query worden alleen de in te vullen gegevens naar de server gestuurd. Het meeste werkt bestaande uit valideren en parsen van de query hoeft dus ook maar een keer uitgevoerd te worden.
De data die naar server verstuurd wordt, hoeft niet door een functie als mysqli_real_escape_string() gehaald te worden. In plaats daarvan werken de MySQL client en server samen om de verstuurde data veilig te verwerken zodra het gecombineerd wordt met het prepared statement.
Voorbeeld 10: Bound parameter prepared statement
<?php
$mysqli = new mysqli('host', 'user', 'password', 'database');
if(mysqli_connect_errno())
{
trigger_error('Fout bij verbinding: '.$mysqli->error);
}
$sql = "
INSERT INTO tabel (naam, email, leeftijd, datum)
VALUES (?, ?, ?, NOW())";
if($stmt = $mysqli->prepare($sql))
{
$stmt->bind_param('ssi', $naam, $email, $leeftijd);
$naam = 'Piet';
$email = '[email protected]';
$leeftijd = '34';
if(!$stmt->execute())
{
echo 'Het uitvoeren van de query is mislukt: '.$stmt->error.' in query: '.$sql;
}
$naam = 'Kees';
$email = '[email protected]';
$leeftijd = '40';
if(!$stmt->execute())
{
echo 'Het uitvoeren van de query is mislukt: '.$stmt->error.' in query: '.$sql;
}
$naam = 'Karel';
$email = '[email protected]';
$leeftijd = '25';
if(!$stmt->execute())
{
echo 'Het uitvoeren van de query is mislukt: '.$stmt->error.' in query: '.$sql;
}
$stmt->close();
}
else
{
echo 'Er zit een fout in de query: '.$mysqli->error;
}
?>
In dit script zien we weer een aantal nieuwe dingen, dus laten we er maar eens stap voor stap doorheen lopen.
Zoals elk script beginnen we natuurlijk weer met het maken van een database verbinding, dat moet nu toch wel al vrij vertrouwd zijn.
Daarna declareren we de SQL query die we gaan gebruiken, of beter gezegd: de template van de query. De template bestaat uit de complete query zonder de gegevens die telkens veranderen. We gebruiken zogenaamde placeholders (?) om aan te geven waar in de query variabele gegevens komen te staan.
De volgende stap is het gebruik van de bind_param() methode. Met deze methode geven we aan van wat voor type de in te voegen variabelen zijn. Als eerste parameter van deze variabele is een string vereist waarmee we het type van de variabelen vastleggen.
Elk teken uit die string komt overeen met een placeholder uit de query template en een extra parameter uit de bind_param() methode. Hierbij kan gebruik gemaakt worden van de volgende tekens die de volgende types aanduiden:
[li]s - De variabele is een string[/li]
[li]i - De variabele is een integer[/li]
[li]d - De variabele is een double of een float[/li]
[li]b - De variabele is een blob[/li]
In bovenstaand voorbeeld houdt 'ssi' in dat de eerste twee variabelen $naam en $email als strings behandeld worden en de variabele $leeftijd als integer. Let erop de de volgorde van genoemde variabelen overeenkomt met de positie van de placeholders in de template.
Let er ook op dat voor elke letter in de eerste parameter van bind_param() er een variabele als paramter meegegeven wordt:
<?php
$stmt->bind_param('s', $string);
$stmt->bind_param('si', $string, $int);
$stmt->bind_param('sid', $string, $int, $float);
?>
In het script worden vervolgens waarden toegekend aan de variabelen en wordt de query uitgevoert met de execute() methode. Vervolgens is het een kwestie van het opnieuw definieren van de variabelen en wederom het aanroepen van de execute() methode. Op deze manier wordt steeds dezelfde INSERT query met verschillende waarden uitgevoerd.
Voorbeeld 11: Een efficientere manier van gegevens verwerken
<?php
$mysqli = new mysqli('host', 'user', 'password', 'database');
if(mysqli_connect_errno())
{
trigger_error('Fout bij verbinding: '.$mysqli->error);
}
$personen = array(
array(
'naam' => 'Piet',
'email' => '[email protected]',
'leeftijd' => 34 ),
array(
'naam' => 'Kees',
'email' => '[email protected]',
'leeftijd' => 40 ),
array(
'naam' => 'Karel',
'email' => '[email protected]',
'leeftijd' => 25 )
);
$sql = "
INSERT INTO tabel (naam, email, leeftijd, datum)
VALUES (?, ?, ?, NOW())";
if($stmt = $mysqli->prepare($sql))
{
$stmt->bind_param('ssi', $naam, $email, $leeftijd);
foreach($personen as $persoon)
{
$naam = $persoon['naam'];
$email = $persoon['email'];
$leeftijd = $persoon['leeftijd'];
if(!$stmt->execute())
{
echo 'Het uitvoeren van de query is mislukt: '.$stmt->error.' in query: '.$sql;
}
}
$stmt->close();
}
else
{
echo 'Er zit een fout in de query: '.$mysqli->error;
}
?>
Dit voorbeeld laat zien dat je gegevens ook uit bijvoorbeeld een array kunt halen. Als je er maar te allen tijde voor zorgt dat de variabelen die voorkomen in de bind_param() methode bestaan en van het juiste type zijn.
Bound Results
De methode voor de bound result prepared statements is bijna hetzelfde als die voor de bound parameter prepared statements. Het enige verschil is dat we nu te maken hebben met gegevens die als resultaat uit een database query komen.
Het stappenplan is als volgt:
[li]Maak een query[/li]
[li]Vraag de MySQL server om de query voor te bereiden[/li]
[li]Koppel PHP variabelen aan kolommen uit de query[/li]
[li]Vraag de MySQL server om de query uit te voeren[/li]
[li]Zorg dat een nieuwe rij met gegevens in de gekoppelde variabelen geladen wordt[/li]
Voorbeeld 12: Bound result prepared statement
<?php
$mysqli = new mysqli('host', 'user', 'password', 'database');
if(mysqli_connect_errno())
{
trigger_error('Fout bij verbinding: '.$mysqli->error);
}
$sql = "
SELECT naam, email, leeftijd
FROM tabel
ORDER BY leeftijd DESC ";
if($stmt = $mysqli->prepare($sql))
{
if(!$stmt->execute())
{
echo 'Het uitvoeren van de query is mislukt: '.$stmt->error.' in query: '.$sql;
}
else
{
$stmt->bind_result($naam, $email, $leeftijd);
while($stmt->fetch())
{
echo $naam.'-'.$leeftijd.'-'.$email.'<br>';
}
}
$stmt->close();
}
else
{
echo 'Er zit een fout in de query: '.$mysqli->error;
}
?>
Met de methode bind_result() is het dus mogelijk om variabelen te koppelen aan de kolomnamen (of indien gebruikt aliassen). Door de fetch() methode in een while loop te plaatsen wordt er door alle rijen uit de resultaat set gelopen en kunnen de gegevens weergegeven worden.
Dit script zal iets opleveren als:
Kees - 40 - [email protected]
Piet - 34 - [email protected]
Karel - 25 - [email protected]
Voorbeeld 13: Een combinatie van bound paramters en bound results
<?php
$mysqli = new mysqli('host', 'user', 'password', 'database');
if(mysqli_connect_errno())
{
trigger_error('Fout bij verbinding: '.$mysqli->error);
}
$sql = "
SELECT naam, leeftijd
FROM tabel
WHERE naam LIKE ?
ORDER BY naam";
if($stmt = $mysqli->prepare($sql))
{
$stmt->bind_param('s', $zoek);
$zoek = 'K%';
if(!$stmt->execute())
{
echo 'Het uitvoeren van de query is mislukt: '.$stmt->error.' in query: '.$sql;
}
else
{
$stmt->bind_result($naam, $leeftijd);
while($stmt->fetch())
{
echo $naam.'-'.$leeftijd.'<br>';
}
}
$stmt->close();
}
else
{
echo 'Er zit een fout in de query: '.$mysqli->error;
}
?>
Hier zien we een combinatie van de twee voorgaande voorbeelden. Allereerst gebruiken we een query template en vragen om die voor te bereiden. Vervolgens koppelen we de benodigde variabelen en laten we het statement uitvoeren.
Daarna gebruiken we de bind_result() methode om de resultaten te koppelen aan variabelen en geven we deze variabelen weer na fetchen van de resultaat set.
Dit scriptje laat duidelijk zien dat de placeholders in de query template ook andere dingen kunnen bevatten dan kolomnamen. Dit gaat allemaal goed, zolang je er maar voor zorgt dat de juiste variabelen aan de query gekoppeld worden en dat deze variabelen de juiste gegevens bevatten.
Reacties
0