PDO - Verbinden met verschillende databases
Gebruik de PDO extensie om verbindingen met verschillende database systemen te onderhouden.
Gesponsorde koppelingen
Inhoudsopgave
- Inleiding
- Gebruik van de PDO extensie
- Uitvoeren van queries
- Foutafhandeling
- Prepared statements
- Transacties
- Slotwoord en referenties
41 reacties op 'PDO - Verbinden met verschillende databases'
Gesponsorde koppelingen
PDO is voornamelijk interessant als je meerdere databases wilt gebruiken of je je code compatible met een andere database wilt houden. Bijvoorbeeld als je in de toekomst nog eens van database wilt switchen.
De MySQLi extensie biedt je meer mysql specifieke methodes die je kunt gebruiken. Deze ontbreken logischerwijs bij PDO aangezien die extensie rekening moet houden met meerdere database systemen.
Als je dus alleen met MySQL werkt, zou ik voor MySQLi gaan.
De MySQLi extensie biedt je meer mysql specifieke methodes die je kunt gebruiken. Deze ontbreken logischerwijs bij PDO aangezien die extensie rekening moet houden met meerdere database systemen.
Als je dus alleen met MySQL werkt, zou ik voor MySQLi gaan.
Quote:
Tja, het maken van de verbinding, het verwerken van de resultaten en de foutafhandeling, die code (php-code wel te verstaan) is inderdaad compatible. Voor de SQL gaat dat helaas niet op, ga bv. maar eens met datums rekenen in MySQL of in PostgreSQL. Dat zijn totaal verschillende functies! Ook voor de datatypes gaat dit op, pgSQL kent meer datatypes en in pgSQL kun je ook je eigen datatypes aanmaken.Nooit meer last van incompatibiliteit van je scripts met een andere database, het is namelijk nog maar een kwestie van 1 regeltje code veranderen.
Het is mogelijk om vrijwel 100% compatibliteit te krijgen, maar dan zul je vrijwel alle functies van de database overboord moeten gooien en standaard datatypes moeten gebruiken. Alleen simpele queries kun je dan nog uitvoeren, de rest van de bewerkingen van de data zul je zelf moeten bouwen. En of je dat wilt? Ik zou er niet aan beginnen, ik laat graag de database een hoop werk voor mij doen.
Desondanks is PDO een uitstekende toepassing. Mocht je van database willen veranderen, dan hoef je uitsluitend de SQL aan te passen.
Ps. Wederom een fraaie tut! Kun je deze tut's niet gaan bundelen en als boekwerkje uit gaan geven? Desnoods als pdf en uitgegeven onder de creative commons.
Iets belangrijks om op te wijzen:
Plaats dus altijd(!) een try / catch statement om de constructor.
Zoals gezegd, je php code hoef je niet aan te passen als je van RDBMS wisselt, zelfs fout codes zijn universeel, zo is de normale error code voor een overschrijding van een unique constraint in MySQL 1062, de PDO code is: 23000
Blanche, erg nette tutorial!
Quote:
If your application does not catch the exception thrown from the PDO constructor, the default action taken by the zend engine is to terminate the script and display a back trace. This back trace will likely reveal the full database connection details, including the username and password. It is your responsibility to catch this exception, either explicitly (via a catch statement) or implicitly via set_exception_handler().
Plaats dus altijd(!) een try / catch statement om de constructor.
Zoals gezegd, je php code hoef je niet aan te passen als je van RDBMS wisselt, zelfs fout codes zijn universeel, zo is de normale error code voor een overschrijding van een unique constraint in MySQL 1062, de PDO code is: 23000
Blanche, erg nette tutorial!
Je methode om een prepared statement in te zetten voor meerdere keren (waarbij je je data uit een array haalt), vind ik niet echt mooi. Je kan namelijk ook een array met parameters meegeven aan $stmt->execute()! Voor de rest een mooie tutorial :)
Ik vind het voordeel van PDO voornamelijk dat je in het geval van hergebruik van bijvoorbeeld een framework niet aan een database gebonden bent.
Uiteraard is het ook mogelijk om de named syntax te hanteren:
Ik vind het voordeel van PDO voornamelijk dat je in het geval van hergebruik van bijvoorbeeld een framework niet aan een database gebonden bent.
Code (php)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<?php
$stmt = $db->prepare( "insert into user (name, password, email) values( ?, ?, ? )" );
$user = array( 'Jan', 'querty', 'jan@querty.nl' );
$stmt->execute( $user );
//of:
$users = array(
array( 'Jan', 'querty', 'jan@querty.nl' ),
array( 'Jan', 'querty', 'jan@querty.nl' ),
array( 'Jan', 'querty', 'jan@querty.nl' )
);
foreach( $users as $user ) {
$stmt->execute( $user );
}
?>
$stmt = $db->prepare( "insert into user (name, password, email) values( ?, ?, ? )" );
$user = array( 'Jan', 'querty', 'jan@querty.nl' );
$stmt->execute( $user );
//of:
$users = array(
array( 'Jan', 'querty', 'jan@querty.nl' ),
array( 'Jan', 'querty', 'jan@querty.nl' ),
array( 'Jan', 'querty', 'jan@querty.nl' )
);
foreach( $users as $user ) {
$stmt->execute( $user );
}
?>
Uiteraard is het ook mogelijk om de named syntax te hanteren:
Code (php)
1
2
3
4
5
2
3
4
5
<?php
$stmt = $db->prepare( "insert into user (name, password, email) values( :name, :password, :email )" );
$user = array( ':name' => 'Jan', ':password' => 'querty', ':email' => 'jan@querty.nl' );
$stmt->execute( $user );
?>
$stmt = $db->prepare( "insert into user (name, password, email) values( :name, :password, :email )" );
$user = array( ':name' => 'Jan', ':password' => 'querty', ':email' => 'jan@querty.nl' );
$stmt->execute( $user );
?>
@Frank: je hebt inderdaad nog incompatiblities tussen databases. Maar het beperkt zich meestal tot het gebruik data en dergelijke. Vaak is het behoorlijk goed dat te ondervangen.
Misschien iets om een universal datum handler class te gebruiken ofzo. Die afhankelijk van wat het gevoerd wordt het omtoverd tot bruikbare resultaten in php? :)
Misschien iets om een universal datum handler class te gebruiken ofzo. Die afhankelijk van wat het gevoerd wordt het omtoverd tot bruikbare resultaten in php? :)
@Arend: Dat valt nog tegen, kijk alleen maar eens naar de verschillende datatypes tussen MySQL en PostgreSQL (deze databases ken ik vrij aardig). Mooi voorbeeld is de TIMESTAMP, die is echt totaal anders. MySQL kent infinity en -infinity (oneindig) niet, daar kun je dus mooi de mist in gaan. Een SERIAL en een INT met auto_increment zijn ook 2 totaal verschillende dingen, helemaal omdat auto_increment nog wel eens een nummer opnieuw wil uitgeven.
Verder gebruik je in pgSQL de || om 2 gegevens aan elkaar te plakken, in MySQL is dit een OR en heb je de functie CONCAT() nodig.
Wil je ?cht de flexibiliteit hebben om van de ene database snel over te kunnen stappen naar de andere database, dan zul je altijd een hoop extra PHP werk moeten verzetten. Je kunt er gewoon niet van uitgaan dat iedere database beschikt over dezelfde functies (al dan niet met een andere naam) en dus zul je deze functie in PHP nogmaals moeten gaan bouwen. En dan komt de aap uit de mouw, ik ben liever lui dan moe...
Kortom, ik bouw een flexibel systeem in PHP en pas op verzoek de SQL aan. Daarmee kan ik toch van de kracht van de database gebruik maken en is het niet alleen maar een bak met gegevens maar een echte DBMS.
Verder gebruik je in pgSQL de || om 2 gegevens aan elkaar te plakken, in MySQL is dit een OR en heb je de functie CONCAT() nodig.
Wil je ?cht de flexibiliteit hebben om van de ene database snel over te kunnen stappen naar de andere database, dan zul je altijd een hoop extra PHP werk moeten verzetten. Je kunt er gewoon niet van uitgaan dat iedere database beschikt over dezelfde functies (al dan niet met een andere naam) en dus zul je deze functie in PHP nogmaals moeten gaan bouwen. En dan komt de aap uit de mouw, ik ben liever lui dan moe...
Kortom, ik bouw een flexibel systeem in PHP en pas op verzoek de SQL aan. Daarmee kan ik toch van de kracht van de database gebruik maken en is het niet alleen maar een bak met gegevens maar een echte DBMS.
Mooie TuT Blanche, een echte aanwinst voor de site.
Ik heb nog wel een kleine op/ aanmerking. In de code bij voorbeeld 19 kan voor sommigen wat onduidelijkheid ontstaan over de regels 22 - 31 (de foreach) wanneer 1 van de 2 regels of updates nu niet wordt uitgevoerd, krijg je wel de melding dat de Update query niets heeft gedaan. (bij beide zou je dit 2 keer krijgen) Ik denk dat het voor de duidelijkheid verstandiger zou zijn om daar:
Dan zie je ook meteen welke rij niet werd geupdate. (het is maar een kleinigheidje, als je de tut snapt snap je dit ook wel)
Ik heb nog wel een kleine op/ aanmerking. In de code bij voorbeeld 19 kan voor sommigen wat onduidelijkheid ontstaan over de regels 22 - 31 (de foreach) wanneer 1 van de 2 regels of updates nu niet wordt uitgevoerd, krijg je wel de melding dat de Update query niets heeft gedaan. (bij beide zou je dit 2 keer krijgen) Ik denk dat het voor de duidelijkheid verstandiger zou zijn om daar:
Dan zie je ook meteen welke rij niet werd geupdate. (het is maar een kleinigheidje, als je de tut snapt snap je dit ook wel)
Ja, dat weet ik wel, maar ook zo:
??
EDIT: Met name de afhandeling
EDIT2: Ik zie hier op PHP.net dit staan:
Code (php)
1
2
3
4
5
6
2
3
4
5
6
<?php
$db = new PDO('mysql:host=localhost;dbname=test','user','password');
$sql = "DELETE FROM tabel WHERE naam = 'Piet'";
$db->exec($sql);
?>
$db = new PDO('mysql:host=localhost;dbname=test','user','password');
$sql = "DELETE FROM tabel WHERE naam = 'Piet'";
$db->exec($sql);
?>
??
EDIT: Met name de afhandeling
EDIT2: Ik zie hier op PHP.net dit staan:
Mooie tutorial, ga gelijk implementeren in mn huidige project maar nog 1 vraag.
Maken jullie elke keer opnieuw een object aan die connectie maak met de DB bij elke query die je uitvoerd?
Of zet je het in een appart bestand die je overal waar nodig include?
En is het nodig om het object de deleten? $db = null; ?
Maken jullie elke keer opnieuw een object aan die connectie maak met de DB bij elke query die je uitvoerd?
Of zet je het in een appart bestand die je overal waar nodig include?
En is het nodig om het object de deleten? $db = null; ?
Je kunt 1 verbinding gerust meerdere keren gebruiken en dus bijvoorbeeld een bestandje includen waarin je die verbinding aanmaakt. Ook is het niet per se nodig om het object te destroyen. Als een script eindigt wordt het object vanzelf vernietigd en de verbinding gesloten...
Pas als je scripts hebt waar je heel veel database acties uitvoert of waarbij het van belang is dat verschillende gebruikers een verbinding kunnen maken (rechten worden verdeeld op database niveau), zou het voordelig kunnen zijn om meerdere connecties te maken en ze ook weer netjes af te sluiten.
Pas als je scripts hebt waar je heel veel database acties uitvoert of waarbij het van belang is dat verschillende gebruikers een verbinding kunnen maken (rechten worden verdeeld op database niveau), zou het voordelig kunnen zijn om meerdere connecties te maken en ze ook weer netjes af te sluiten.
Is het niet mogelijk om hibernate met php te koppelen? Ik heb dit gebruikt in Java en het werkte echt perfect. Hoef je ook geen queries meer te maken en kan je de database echt makkelijk overzetten. Ik heb er ooit eens iets over gelezen dat het mogelijk is met PHP. Weten jullie er misschien iets meer van?
@Michael: Je bedoelt zoiets als Propel?
Dikke ellende, je verliest met dit soort zaken vrijwel alle pluspunten van een database. Performance is dan ook om te huilen.
Daarnaast is het niet nodig om een (PHP-) programmeur lastig te vallen met queries, geef hem/haar gewoon een API en klaar is kees. De DBA kan dan in de database deze API kan bouwen en beheren, dat zal vele malen sneller en veiliger zijn. Databases als DB2, Oracle, PostgreSQL en SQL Server kennen allemaal de mogelijkheid om met stored procedures, views, etc. te werken. Dat maakt het leven voor de programmeur vele malen eenvoudiger, een simpele query als
is echt niet moeilijk te intergreren.
Dikke ellende, je verliest met dit soort zaken vrijwel alle pluspunten van een database. Performance is dan ook om te huilen.
Daarnaast is het niet nodig om een (PHP-) programmeur lastig te vallen met queries, geef hem/haar gewoon een API en klaar is kees. De DBA kan dan in de database deze API kan bouwen en beheren, dat zal vele malen sneller en veiliger zijn. Databases als DB2, Oracle, PostgreSQL en SQL Server kennen allemaal de mogelijkheid om met stored procedures, views, etc. te werken. Dat maakt het leven voor de programmeur vele malen eenvoudiger, een simpele query als
is echt niet moeilijk te intergreren.
Als het iemand interesseert, ik ben bezig een (wrapper) class aan het maken om wat gemakkelijker dit alles te kunnen toepassen.
Zo'n class maken, is trouwens een goeie oefening om dit alles onder de knie te krijgen.
Mooie tutorial.
Misschien een detail:
In een paar voorbeelden zet je een leeftijd in de database.
Een leeftijd is een afgeleid veld. Geboortedatum zou beter zijn.
Maar, het is dus maar een detail.
Zo'n class maken, is trouwens een goeie oefening om dit alles onder de knie te krijgen.
Mooie tutorial.
Misschien een detail:
In een paar voorbeelden zet je een leeftijd in de database.
Een leeftijd is een afgeleid veld. Geboortedatum zou beter zijn.
Maar, het is dus maar een detail.
Voorbeeld 18: Statement uitvoeren met gegevensarray als parameter
ik heb een kleine aanpassing van de querie gedaan..
IF NOT EXISTS ( SELECT email FROM tabel WHERE email = :email)
INSERT INTO tabel (naam, leeftijd, email)
VALUES (:naam, :leeftijd, :email)
maar krijg hierop een error
Foutmelding: SQLSTATE[HY000]: General error: 10038 Attempt to initiate a new SQL Server operation with results pending. [10038] (severity 7) [(null)]
hoe kan ik men resultset vrij laten?
voor de rest een goede tutorial, nu kan ik deftig sqlinjection tegen gaan.
Thx
bart
ik heb een kleine aanpassing van de querie gedaan..
IF NOT EXISTS ( SELECT email FROM tabel WHERE email = :email)
INSERT INTO tabel (naam, leeftijd, email)
VALUES (:naam, :leeftijd, :email)
maar krijg hierop een error
Foutmelding: SQLSTATE[HY000]: General error: 10038 Attempt to initiate a new SQL Server operation with results pending. [10038] (severity 7) [(null)]
hoe kan ik men resultset vrij laten?
voor de rest een goede tutorial, nu kan ik deftig sqlinjection tegen gaan.
Thx
bart
Hi,
Dit is nog een leuke variant met BindValue.
$hostname = 'localhost';
$username = '';
$password = '';
$dbname = 'test';
try {
$dbh = new PDO("mysql:host=$hostname;dbname=$dbname", $username, $password);
/*** echo a message saying we have connected ***/
/*** set the error reporting attribute ***/
$dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
/*** some variables ***/
$data = array('username'=>'name', 'password'=>'pass', 'status'=>'on hold');
$keys = implode(", ", array_keys($data));
$keyparam = ':'.implode(", :", array_keys($data));
$values = implode(", ", array_values($data));
$table = 'users';
$sql = "INSERT INTO $table ($keys) VALUES ($keyparam)";
$stmt = $dbh->prepare($sql);
foreach($data as $k => $v){ $stmt->BindValue(':'.$k ,$v); }
$stmt->execute();
$stmt = $dbh->prepare("SELECT * FROM $table");
$stmt->execute();
$result = $stmt->fetchAll();
foreach($result as $row)
{
foreach(array_keys($data) as $item){
echo ' :: '.$row[$item].' :: ';
}
echo '<br />';
}
/*** close the database connection ***/
$dbh = null;
}
catch(PDOException $e)
{
echo $e->getMessage();
}
Bedankt voor de tutorial.
Dit is nog een leuke variant met BindValue.
$hostname = 'localhost';
$username = '';
$password = '';
$dbname = 'test';
try {
$dbh = new PDO("mysql:host=$hostname;dbname=$dbname", $username, $password);
/*** echo a message saying we have connected ***/
/*** set the error reporting attribute ***/
$dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
/*** some variables ***/
$data = array('username'=>'name', 'password'=>'pass', 'status'=>'on hold');
$keys = implode(", ", array_keys($data));
$keyparam = ':'.implode(", :", array_keys($data));
$values = implode(", ", array_values($data));
$table = 'users';
$sql = "INSERT INTO $table ($keys) VALUES ($keyparam)";
$stmt = $dbh->prepare($sql);
foreach($data as $k => $v){ $stmt->BindValue(':'.$k ,$v); }
$stmt->execute();
$stmt = $dbh->prepare("SELECT * FROM $table");
$stmt->execute();
$result = $stmt->fetchAll();
foreach($result as $row)
{
foreach(array_keys($data) as $item){
echo ' :: '.$row[$item].' :: ';
}
echo '<br />';
}
/*** close the database connection ***/
$dbh = null;
}
catch(PDOException $e)
{
echo $e->getMessage();
}
Bedankt voor de tutorial.
Om te reageren heb je een account nodig en je moet ingelogd zijn.
- Details
Door:
Joren de Wit- 6 jaar geleden
- 7.016 x bekeken
- Labels
- Geen tags toegevoegd.
- PHP tutorials opties
- Overig
- Nieuwste PHP tutorials
- PHP tutorial toevoegen


PHP hulp
0 seconden vanaf nu