2012-08-12, 16:08
#1
Jag skapar den här tråden som en typ av svar till den klistrade tråden Ska du sätta ihop en SQL dynamiskt, SE HIT!! även om Proton i sitt inlägg länkar till en guide angående PDO tänkte jag att det kan vara bra att ha en här på forumet också!
Som Proton skriver så handlar de flesta frågorna angående PHP/SQL varför mitt mysql_ anrop inte fungerar, så kanske denna tråden kan öppna ögonen för PDO!
Varför använda PDO över mysql_* ?
Då sätter vi igång - Anslut till din databas
För att skapa en anslutning till våran databas brukade vi göra på detta tråkiga sättet.
mysql_ :
[php]
<?PHP
$db = mysql_connect('localhost', 'username', 'password'); //Skapa en anslutning
mysql_select_db('db_name', $db); //Välj vilken databas vi arbetar emot
?>
[/php]
PDO:
[php]
<?PHP
$db = new PDO('mysql:host=localhost;dbname=db_name;charset=u tf8', 'username', 'password');
?>
[/php]
Egentligen bör vi även passa ett till argument som stänger av "Prepare emulate" som är satt till true som standard.
Prepare Emulate används för att hantera äldre versioner av MySQL.
Vi sätter också ERRMODE till EXCEPTION.
[php]
<?PHP
$db = new PDO('mysql:host=localhost;dbname=db_name;charset=u tf8', 'username', 'password');
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$db->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
/*
Vi skapar ett nytt PDO objekt som tar max fyra stycken argument
DSN - en sträng med anslutningsalternativ (host, databasnamn och charset)
Användarnamn, lösenord
Och en array med drivrutinsalternativ ( I detta fallet passar vi inte argumenten direkt utan använder oss utav funktionen setAttribute();
*/
?>
[/php]
Läs mer om alla argument som PDO tar HÄR
Okej, så vi har en anslutning till våran databas!.
Vi går vidare med några select statements!
Ponera att vi har en databas med användare, vi vill hämta ut information från en specifik användare med namnet $username samt lösenord $password.
mysql_ :
[php]
<?PHP
$query = "SELECT * FROM users WHERE username = '$username' AND password='$password'";
$sql = mysql_query($query);
?>
[/php]
PDO :
[php]
<?PHP
$stmt = $db->prepare("SELECT * FROM users username=? AND password=?");
$stmt->execute(array($name, $password));
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
?>
[/php]
Att använda detta underlättar kanske inte just i detta fallet när vi passar två parameter (username,password)
men det underlättar väldigt mycket när du har en hel hög som skall jämföras mot databasen.
Vi använder placeholdern "?", även detta kan bli förvirrande när man skickar med många prarmetrar.
Därför finns även placeholdern ":"
[php]
<?PHP
$stmt = $db->prepare("SELECT * FROM users WHERE username=:username AND password=
assword");
$stmt->execute(array(':username' => $username, '
assword' => $password));
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
?>
[/php]
Kom ihåg att detta är bara ett utav väldigt många sätt att köra select statements på!
Läs mer om hur du exekverar querys HÄR och HÄR
Räkna rader med rowCount()
Vi har kört vårat select statement, men nu vill vi veta hur många rader (om några) som vi hittade.
Istället för att använda mysql_num_rows($sql) använder vi funktionen rowCount() !
[php]
<?PHP
// Vårat prepared statement ..
$rowCount = $stmt->rowCount();
echo $rowCount . " rader valdes";
?>
[/php]
INSERT, UPDATE, DELETE
Egentligen ingen större skillnad mot våra select statements, förutom våran query dvs.
Jag fattar mig kort här!
[php]
// Lägg till användare ($username, $password)
$stmt = $db->prepare("INSERT INTO users(username, password) VALUES(:username,
assword)");
$stmt->execute(array(':username' => $username, '
assword' => $password));
// Uppdatera en användare ($username, $password)
$stmt = $db->prepare("UPDATE users SET password=
assword WHERE username=:username");
$stmt->execute(array(':username' => $username, '
assword' => $password));
// Ta bort en användare ($username)+
$stmt = $db->prepare("DELETE FROM users WHERE username=:username");
$stmt->execute(array(':username' => $username));
[/php]
Detta är exempel på hur vi kan lägga till, uppdatera och ta bort användare.
Även om man i vanliga fall använder ett id för att välja användare.
Vi vill ju givetvis kolla om någon rad har blivit påverkad för att få någon sorts bekräftning.
Då kör vi våran funktion rowCount() på samma sätt som innan!
[php]
<?PHP
$rowCount = $stmt->rowCount();
echo $rowCount . " rader påverkade!";
?>
[/php]
Felhanteringen då?
Givetvis ger PDO oss möjligheter att kolla vad som gick snett i våra anrop till SQL, bättre än föregångaren die(mysql_error()); dessutom!
[php]
<?PHP
// Lägg märke till felstavningen i FROM/FRMO
$query = "SELECT * FRMO users WHERE username='$username' AND password='$password'";
$sql = mysql_query($query) or die(mysql_error());
?>
[/php]
"or die()" går inte att hantera på ett bra sätt utan den avslutar ditt PHP script prompt!
Den skriver dessutom ut en ruta med all information den kunde hitta angående felet, något man oftast inte vill visa för användaren av sidan.
Hur gör vi med PDO istället då?
Vi har olika error modes.
PDO::ERRMODE_SILENT - fungerar på liknande sätt som mysql_error(), du måste kolla alla resultat och sedan inspektera $db->errorInfo();
PDO::ERRMODE_WARNING - Kastar varningar
PDO::ERRMODE_EXCEPTION - Kastar exceptions, fungerar också på liknande sätt som die(mysql_error()) när man inte fångar detta, men använder man en try/catch sats kan man göra detta väldigt bra!
Det fina med PDO är också att du inte behöver fånga errormeddelanden direkt efter att ett anrop har skett.
Exempel nedan där vi har en funktion som hämtar information om en användare och returnerar denna.
[php]
<?PHP
function selectUser($db, $username, $password) {
$stmt = $db->prepare("SELECT * FROM users WHERE username=:username AND password=
assword");
$stmt->execute(array(':username' => $username, '
assword' => $password));
return $stmt->fetchAll(PDO::FETCH_ASSOC);
}
try {
selectUser($db,$username,$password);
} catch(PDOException $ex) {
// Hantera det fångade felmeddelandet.
}
[/php]
Läs mer om felhanteringen i PDO - HÄR
Det finns väldigt mycket mer att ta upp, men allting jag tagit upp står i PHP.net's dokumentation
Om det är någonting som ser helt galet ut i inlägget, påpeka gärna det!
Jag har själv precis börjat använda PDO (Borde gjort detta för ett bra tag sedan) och jag uppskattar det verkligen även om jag har bra mycket mer att lära mig.
Kommentarer uppskattas
Som Proton skriver så handlar de flesta frågorna angående PHP/SQL varför mitt mysql_ anrop inte fungerar, så kanske denna tråden kan öppna ögonen för PDO!
Varför använda PDO över mysql_* ?
- mysql_* funktionerna är gamla och ouppskattade, det har inte stöd för nyare databaser vilket PDO har.
- PHP.net utvecklar eller underhåller inte längre mysql_* funktionerna och således patchas inga säkerhetshål som kan komma att upptäckas!
- mysql_ kommer försvinna helt vid en viss punkt (Antagligen inte idag eller imorgon) och då är det lika bra att lära sig ett nytt och fräsht sätt att hantera sql-anrop redan idag!
- Med PDO kommer dina querys dessutom bli vackrare och det blir lättare att skriva läsbar och fin kod.
- Med PDO har du dessutom stöd för alla databaser via olika drivrutiner som är lätt att installera (php-mysql)
- Du behöver inte escapea variabler med prepared statements, vilket gör att SQL injections blir svårare att utföra!
Citat:
This extension is not recommended for writing new code. Instead, either the mysqli or PDO_MySQL extension should be used. See also the MySQL API Overview for further help while choosing a MySQL API.
Då sätter vi igång - Anslut till din databas
För att skapa en anslutning till våran databas brukade vi göra på detta tråkiga sättet.
mysql_ :
[php]
<?PHP
$db = mysql_connect('localhost', 'username', 'password'); //Skapa en anslutning
mysql_select_db('db_name', $db); //Välj vilken databas vi arbetar emot
?>
[/php]
PDO:
[php]
<?PHP
$db = new PDO('mysql:host=localhost;dbname=db_name;charset=u tf8', 'username', 'password');
?>
[/php]
Egentligen bör vi även passa ett till argument som stänger av "Prepare emulate" som är satt till true som standard.
Prepare Emulate används för att hantera äldre versioner av MySQL.
Vi sätter också ERRMODE till EXCEPTION.
[php]
<?PHP
$db = new PDO('mysql:host=localhost;dbname=db_name;charset=u tf8', 'username', 'password');
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$db->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
/*
Vi skapar ett nytt PDO objekt som tar max fyra stycken argument
DSN - en sträng med anslutningsalternativ (host, databasnamn och charset)
Användarnamn, lösenord
Och en array med drivrutinsalternativ ( I detta fallet passar vi inte argumenten direkt utan använder oss utav funktionen setAttribute();
*/
?>
[/php]
Läs mer om alla argument som PDO tar HÄR
Okej, så vi har en anslutning till våran databas!.
Vi går vidare med några select statements!
Ponera att vi har en databas med användare, vi vill hämta ut information från en specifik användare med namnet $username samt lösenord $password.
mysql_ :
[php]
<?PHP
$query = "SELECT * FROM users WHERE username = '$username' AND password='$password'";
$sql = mysql_query($query);
?>
[/php]
PDO :
[php]
<?PHP
$stmt = $db->prepare("SELECT * FROM users username=? AND password=?");
$stmt->execute(array($name, $password));
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
?>
[/php]
Att använda detta underlättar kanske inte just i detta fallet när vi passar två parameter (username,password)
men det underlättar väldigt mycket när du har en hel hög som skall jämföras mot databasen.
Vi använder placeholdern "?", även detta kan bli förvirrande när man skickar med många prarmetrar.
Därför finns även placeholdern ":"
[php]
<?PHP
$stmt = $db->prepare("SELECT * FROM users WHERE username=:username AND password=
assword");$stmt->execute(array(':username' => $username, '
assword' => $password));$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
?>
[/php]
Kom ihåg att detta är bara ett utav väldigt många sätt att köra select statements på!
Läs mer om hur du exekverar querys HÄR och HÄR
Räkna rader med rowCount()
Vi har kört vårat select statement, men nu vill vi veta hur många rader (om några) som vi hittade.
Istället för att använda mysql_num_rows($sql) använder vi funktionen rowCount() !
[php]
<?PHP
// Vårat prepared statement ..
$rowCount = $stmt->rowCount();
echo $rowCount . " rader valdes";
?>
[/php]
INSERT, UPDATE, DELETE
Egentligen ingen större skillnad mot våra select statements, förutom våran query dvs.
Jag fattar mig kort här!
[php]
// Lägg till användare ($username, $password)
$stmt = $db->prepare("INSERT INTO users(username, password) VALUES(:username,
assword)");$stmt->execute(array(':username' => $username, '
assword' => $password));// Uppdatera en användare ($username, $password)
$stmt = $db->prepare("UPDATE users SET password=
assword WHERE username=:username");$stmt->execute(array(':username' => $username, '
assword' => $password));// Ta bort en användare ($username)+
$stmt = $db->prepare("DELETE FROM users WHERE username=:username");
$stmt->execute(array(':username' => $username));
[/php]
Detta är exempel på hur vi kan lägga till, uppdatera och ta bort användare.
Även om man i vanliga fall använder ett id för att välja användare.
Vi vill ju givetvis kolla om någon rad har blivit påverkad för att få någon sorts bekräftning.
Då kör vi våran funktion rowCount() på samma sätt som innan!
[php]
<?PHP
$rowCount = $stmt->rowCount();
echo $rowCount . " rader påverkade!";
?>
[/php]
Felhanteringen då?
Givetvis ger PDO oss möjligheter att kolla vad som gick snett i våra anrop till SQL, bättre än föregångaren die(mysql_error()); dessutom!
[php]
<?PHP
// Lägg märke till felstavningen i FROM/FRMO
$query = "SELECT * FRMO users WHERE username='$username' AND password='$password'";
$sql = mysql_query($query) or die(mysql_error());
?>
[/php]
"or die()" går inte att hantera på ett bra sätt utan den avslutar ditt PHP script prompt!
Den skriver dessutom ut en ruta med all information den kunde hitta angående felet, något man oftast inte vill visa för användaren av sidan.
Hur gör vi med PDO istället då?
Vi har olika error modes.
PDO::ERRMODE_SILENT - fungerar på liknande sätt som mysql_error(), du måste kolla alla resultat och sedan inspektera $db->errorInfo();
PDO::ERRMODE_WARNING - Kastar varningar
PDO::ERRMODE_EXCEPTION - Kastar exceptions, fungerar också på liknande sätt som die(mysql_error()) när man inte fångar detta, men använder man en try/catch sats kan man göra detta väldigt bra!
Det fina med PDO är också att du inte behöver fånga errormeddelanden direkt efter att ett anrop har skett.
Exempel nedan där vi har en funktion som hämtar information om en användare och returnerar denna.
[php]
<?PHP
function selectUser($db, $username, $password) {
$stmt = $db->prepare("SELECT * FROM users WHERE username=:username AND password=
assword");$stmt->execute(array(':username' => $username, '
assword' => $password));return $stmt->fetchAll(PDO::FETCH_ASSOC);
}
try {
selectUser($db,$username,$password);
} catch(PDOException $ex) {
// Hantera det fångade felmeddelandet.
}
[/php]
Läs mer om felhanteringen i PDO - HÄR
Det finns väldigt mycket mer att ta upp, men allting jag tagit upp står i PHP.net's dokumentation
Om det är någonting som ser helt galet ut i inlägget, påpeka gärna det!
Jag har själv precis börjat använda PDO (Borde gjort detta för ett bra tag sedan) och jag uppskattar det verkligen även om jag har bra mycket mer att lära mig.
Kommentarer uppskattas