PDO MySQL Grunder
Vad är MySQL
MySQL är en databashanterare. Gratis att använda under GNU General Public License. MySQL utvecklades och såldes av MySQL AB som hade sitt kontor i Uppsala. 2008 såldes företaget till Sun som i sin tur köptes upp av Oracle 2010.
Vad är PDO
PHP-PDO-MySQL grunder
Del 0- Förutsättningar
Nu ska vi lära oss att manipulera
en MySQL databas m h a PHP. Vi förutsätter att den finns(här:
mindatabas) och att du har användarnamn(här: per) och lösenord(här:
hemligt) till databasen.
Vi kommer i flera steg bygga upp våra webbsidor:
1. Skapa en tabell med datafält(kolumner)
2. Visa alla dataposter
3. Lägga till dataposter
4. Modifiera befintlig datapost
5. Ta bort datapost
6. Ta bort hel tabell
Del 1 - Skapa en tabell med datafält(kolumner)
Vi ska skapa en tabell, testtabell, med följande kolumner::
index nummer - idx - som ska vara ett heltal, som ska vara unikt och som
lämpligast räknas upp automatiskt så fort det läggs
till en ny post
Förnamn - fornamn - ska avar ett textfält på max 20 tecken
Efternamn - efternamn - ska avar ett textfält på max 30 tecken
Ålder - alder - som ska vara ett heltal
+-----------+--------------+------+------------+---------+-------------+
| Field | Type | Null | Key | Default | Extra | +-----------+--------------+------+------------+---------+-------------+ | idx | int(3) | NO |primärnyckel| NULL |autoincrement| | fornamn | varchar(20) | YES | | NULL | | | efternamn | varchar(30) | YES | | NULL | | | alder | int | YES | | NULL | | +-----------+--------------+------+------------+---------+-------------+
<!-- createtable.php -->
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>Create</title>
</head>
<body>
<?php
include ('dbconnection.php');
try {
// sql to create table
$sql = "CREATE TABLE pdodemotable (
id INT(6) UNSIGNED AUTO_INCREMENT PRIMARY KEY,
firstname VARCHAR(30) NOT NULL,
lastname VARCHAR(30) NOT NULL,
age INT,
reg_date DATETIME
)";
// use exec() because no results are returned
$dbconn->exec($sql);
echo "Table created successfully";
}
catch(PDOException $e)
{
echo $sql . "<br>" . $e->getMessage();
}
//Rensa kopplingen till databasen
$dbconn = null;
?>
</body>
</html>
Med följande rad så bygger vi ihop MySQL-kommandot och
placerar i en variabel:
$sql = "CREATE TABLE pdodemotable (
id INT(6) UNSIGNED AUTO_INCREMENT PRIMARY KEY,
firstname VARCHAR(30) NOT NULL,
lastname VARCHAR(30) NOT NULL,
age INT,
reg_date DATETIME
)";
kolumnerna heter id, firstname, lastname, age och reg_date. Den första, id, blir automatiskt uppräknad varje gång man lägger in en ny post i tabellen och den startar på ett. De övriga är textfält 20 respektive 30 tecken långa och ett heltal samt datum med tid.
Vi utför anropet till databasen med:
try {
...
// use exec() because no results are returned
$dbconn->exec($sql);
echo "Table created successfully";
}
catch(PDOException $e)
{
echo $sql . "<br>" . $e->getMessage();
}
och sätter allt i en "try and catch" sats. Skriver ut om det går bra, tar hand om felmeddelandet om det inte går bra.
$dbconn innehåller information om själva kopplingen till databasen
och kan vara lämplig att lägga i en separat fil som inkluderas
i samtliga filer som ska arbeta mot databasen. Vi tittar närmare
på den filen:
<!-- dbconnection.php -->
<?php
$dbname = 'mindatabas';
$hostname = 'localhost';
$DB_USER = 'root';
$DB_PASSWORD = '';
$options = array(PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES 'UTF8'");
try {
$dbconn = new PDO("mysql:host=$hostname;dbname=$dbname;", $DB_USER, $DB_PASSWORD, $options);
$dbconn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
/*** echo a message saying we have connected ***/
echo 'Connected to database.<br />';
}
catch(PDOException $e){
// For debug purpose, shows all connection details
echo 'Connection failed: '.$e->getMessage()."<br />";
// Hide connection details.
//echo 'Could not connect to database.<br />');
}
Vi kopplar upp oss mot databasen med "localhost" som betyder att databasen
finns på den lokala datorn, dvs där du befinner dig.
"username" och "password" är där du ska skriva ditt eget databasanvändarnamn och databaslösenord.
Sen tar vi och väljer den databas (här "mindatabas", du måste veta namnet på din)som vi ska arbeta i (ibland har man bara tillgång till en enda men i
andra fall kan man skapa dessa själva)
Del 2 - Visa innehållet i en tabell i en databas
<!-- selectposts.php -->
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>Select</title>
</head>
<body>
<?php
include ('dbconnection.php');
try {
/*** The SQL SELECT statement ***/
$sql = "SELECT * FROM pdodemotable";
$stmt = $dbconn->prepare($sql);
// parameters in array, if empty we could skip the $data-variable
$data = array();
$stmt->execute($data);
$res = $stmt->fetchAll();
$output = htmlentities(print_r($res, 1));
echo "<pre>$output</pre>";
// fetch width column names
$data = array();
$stmt->execute($data);
$res = $stmt->fetch(PDO::FETCH_ASSOC);
$output = htmlentities(print_r($res, 1));
echo "<pre>$output</pre>";
// fetch columnindex
$data = array();
$stmt->execute($data);
$res = $stmt->fetch(PDO::FETCH_NUM);
$output = htmlentities(print_r($res, 1));
echo "<pre>$output</pre>";
// fetch width column names, create a table
$data = array();
$stmt->execute($data);
$output = "<table><caption>En ostylad tabell!</caption>";
while ($res = $stmt->fetch(PDO::FETCH_ASSOC)) {
$output .= "<tr>".
"<td>".htmlentities($res['id'])."</td>".
"<td>".htmlentities($res['firstname'])."</td>".
"<td>".htmlentities($res['lastname'])."</td>".
"<td>".htmlentities($res['age'])."</td>".
"<td>".htmlentities($res['reg_date'])."</td>".
"</tr>";
}
$output .= "</table>";
echo "$output";
}
catch(PDOException $e)
{
echo $sql . "<br />" . $e->getMessage();
}
$dbconn = null;
?>
</body>
</html>
Vi använder
MySQL kommandot SELECT för att hämta data från tabellen.
Vi lägger hela kommandot i en variabel, $sql, sen kopplar vi upp oss mot databasen och preparerar för att köra mysql-anropet.
När vi kör kommandot med kommandot execute så skickar vi med en array med information. Om det inte finns någon informationen så låter vi arrayen bara vara tom. Sen hämtar vi ut svaret med fetchAll eller fetch och skriver ut på lämpligt sätt..
För mer information om dessa funktioner se http://www.php.net.
Vi hämtar ut innehållet i vår $res-variabel som är en array med kolumnnamnen som argument. Vi passar på att översätta farliga tecken med dess entiteter. Detta så att inget konstigt skrivs i webbläsaren.
Mycket går givetvis att korta ner allt men ibland är det bättre att göra ett steg mer och få en bra struktur.
Del 3 - Lägg till innehåll i en tabell i en databas
Först skapar vi en fil som enbart dumpar in lite statisk information i vår tabell. Detta är bra om vi tar bort tabellen och skapar en ny, så kan vi snabbt stoppa in samma startvärden i tabellen.
<!-- insertdefaultposts.php -->
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>Namnlöst dokument</title>
</head>
<body>
<?php
include ('dbconnection.php');
try {
$sql = "INSERT INTO pdodemotable (firstname, lastname, age, reg_date)
VALUES ('Kalle', 'Anka', 120, now())";
// use exec() because no results are returned
$dbconn->exec($sql);
/*** prepare the SQL statement ***/
$sql = "INSERT INTO pdodemotable (firstname, lastname, age, reg_date)
VALUES ('Åsa', 'Anka', 110, now())";
$stmt = $dbconn->prepare($sql);
/*** execute the prepared statement ***/
$stmt->execute();
# sql
$sql = "INSERT INTO pdodemotable (firstname, lastname, age, reg_date)
VALUES (?, ?, ?, now())";
# prepare
$stmt = $dbconn->prepare($sql);
# the data we want to insert
$data = array('Östen', 'Anka', 90);
# execute width array-parameter
$stmt->execute($data);
$data = array('Amanda', 'Anka', 800);
$stmt->execute($data);
$data = array('Per', 'Anka', 70);
$stmt->execute($data);
echo "New records created successfully";
}
catch(PDOException $e)
{
echo $sql . "<br>" . $e->getMessage();
}
$dbconn = null;
?>
</body>
</html>
Nästa sida för inmatning, se nedan.
Här använder vi formulär för inmatningen som sen skickas
vidare till en annan fil som tar hand om införandet i databasen.
Antar att du känner igen formulär och kan använda det. Detta
är ett enkelt formulär som skickar informationen från de
olika komponeterna till samma fil.
Vi fyller här i minst 2 textsträngar och eventuellt ett heltal.
Observera att vi döpt de 3 textfälten till samma namn som vi använde
i databasen. Det är inte nödvändigt men ganska bekvämt.
Låt oss nu hoppa till filen som tar hand om informationen.
<!-- insertpost.php -->
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>Namnlöst dokument</title>
</head>
<body>
<?php
$message = null;
if (isset($_POST['firstname']) && isset($_POST['lastname']) &&
!empty($_POST['firstname']) && !empty($_POST['lastname'])) {
$firstname = $_POST['firstname'];
$lastname = $_POST['lastname'];
$age = isset($_POST['age']) ? $_POST['age'] : 0;
include ('dbconnection.php');
try {
# prepare
$sql = "INSERT INTO pdodemotable (firstname, lastname, age, reg_date)
VALUES (?, ?, ?, now())";
$stmt = $dbconn->prepare($sql);
# the data we want to insert
$data = array($firstname, $lastname, $age);
# execute width array-parameter
$stmt->execute($data);
echo "New record created successfully";
$lastId = $dbconn->lastInsertId();
echo "id på sista posten: $lastId";
}
catch(PDOException $e)
{
echo $sql . "<br>" . $e->getMessage();
}
$dbconn = null;
} else {
$message .= "<br />Du måste fylla i förnamn och efternamn!<br /><br />";
}
echo $message;
?>
<form method="post" action="">
<table>
<tr>
<td>Förnamn*:</td>
<td><input type="text" name="firstname" size=40 maxlength=100>
</td>
</tr>
<tr>
<td>Efternamn*:</td>
<td><input type="text" name="lastname" size=40 maxlength=100></td></tr>
<tr><td>Ålder:</td><td><input type="text" name="age" size=20 maxlength=20></td></tr>
<tr>
<td>* = obligatoriskt</td>
<td><button type="submit">Lägg till</button></td></tr>
</table>
</form>
</body>
</html>
Lite förklaring till sidan:
Den första delen tar emot data från formuläret om det hade skickats något (dvs att man klickat på skicka-knappen i formuläret) och stoppar in det i tabellen.
Vi plockar ut informationen som fördes över från formulärsidan
med $_POST[namn på fält(komponent) i formuläret]
som är superglobal.
Vi behöver inte rensa indata mer genom att vi separerar sql-kommandot och värdena som bifogas i en separat array. Om man inte använder PDO utan vanliga mysql-anrop så måste man här rensa indata för att undvika en del möjliga hackerattacker genom att rensa med mysqli_real_escape_string( ).
Som vanligt skapar vi kontakt med databasen först och sen skickar
vi följande kommandon till databasen:
$sql = "INSERT INTO pdodemotable (firstname, lastname, age, reg_edit)
VALUES (?, ?, ?, now())";
$stmt = $dbconn->prepare($sql);
$data = array($firstname, $lastname, $age);
$stmt->execute($data);
Kommandot tar värden som skickades från formulärsidan
och stoppar in dom i tabellen i databasen. Vi behöver inte skicka med något för kolumnen id som har "auto_increment" för här ska databasen själv räkna
upp (auto_increment) det fältet så det alltid blir unikt.
Frågetecknen matchar respektive värden i data-arrayen.
För att inte MySQLkommandot ska utföras utan att vi har data
så testar vi allra först att variablerna innehåller något
med den färdiga funktionen isset() och !empty(). Det vill säga de ska ha ett värde och värdet ska inte vara tom textsträng.
Del 4 - Modifiera innehåll i en tabell i en databas
Antag att vi vill ändra något i någon av posterna i tabellen,
då måste vi först välja vilken post, sen få
den postens data att hamna i ett formulär så vi kan ändra
och slutligen så skickar vi den uppdaterade datan för
ändring i tabellen i databasen.
Här har vi allt i en och samma fil:
<!-- updatepost.php -->
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>Update</title>
</head>
<body>
<?php
include ('dbconnection.php');
$message = null;
$getid = null;
$getfirstname = null;
$getlastname = null;
$getage = null;
if (isset($_POST['firstname']) && isset($_POST['lastname']) &&
isset($_POST['id']) && !empty($_POST['firstname']) &&
!empty($_POST['lastname']) && !empty($_POST['id'])) {
$id = $_POST['id'];
$firstname = $_POST['firstname'];
$lastname = $_POST['lastname'];
$age = isset($_POST['age']) ? $_POST['age'] : 0;
try {
# prepare
$sql = "UPDATE pdodemotable SET firstname=?, lastname=?, age=?
WHERE id=?";
$stmt = $dbconn->prepare($sql);
# the data we want to insert
$data = array($firstname, $lastname, $age, $id);
# execute width array-parameter
$stmt->execute($data);
$message .= "<br />Record updated successfully.<br />";
// clear form from info
$_GET['id'] = null;
}
catch(PDOException $e)
{
$message .= $sql . "<br>" . $e->getMessage();
}
} else {
$message .= "<br />Först väljer du en post.
Sen måste du fylla i minst förnamn och efternamn!<br /><br />";
}
if (isset($_GET['id']) && !empty($_GET['id']) ) {
$id = $_GET['id'];
try {
# prepare
$sql = "SELECT * FROM pdodemotable WHERE id=?";
$stmt = $dbconn->prepare($sql);
# the data we want to insert
$data = array($id);
# execute width array-parameter
$stmt->execute($data);
$res = $stmt->fetch(PDO::FETCH_ASSOC);
$getid = htmlentities($res['id']);
$getfirstname = htmlentities($res['firstname']);
$getlastname = htmlentities($res['lastname']);
$getage = htmlentities($res['age']);
$message .= "<br />Record was selected successfully.<br />";
}
catch(PDOException $e)
{
$message .= $sql . "<br>" . $e->getMessage();
}
} else {
$message .= "<br />Välj en ny post att uppdatera.<br /><br />";
}
echo $message;
?>
<form method="post" action="">
<table>
<tr>
<td>Förnamn*:</td>
<td>
<input type="text" name="firstname" size="40" maxlength="40"
value="<?= $getfirstname; ?>">
</td>
</tr>
<tr>
<td>Efternamn*:</td>
<td>
<input type="text" name="lastname" size="40" maxlength="40"
value="<?= $getlastname; ?>">
</td>
</tr>
<tr>
<td>Ålder:</td>
<td>
<input type="text" name="age" size="20" maxlength="20"
value="<?= $getage; ?>">
</td>
</tr>
<tr>
<td>* = obligatoriskt</td>
<td>
<button type="submit">Lägg till</button>
<input type="hidden" name="id" value="<?= $getid; ?>">
</td>
</tr>
</table>
</form>
<?php
// Ouput table with all posts
/*** The SQL SELECT statement ***/
$sql = "SELECT * FROM pdodemotable";
$stmt = $dbconn->prepare($sql);
// fetch width column names, create a table
$data = array();
$stmt->execute($data);
$output = "<table><caption>En ostylad tabell!</caption>";
while ($res = $stmt->fetch(PDO::FETCH_ASSOC)) {
$idx = htmlentities($res['id']);
$first = htmlentities($res['firstname']);
$last = htmlentities($res['lastname']);
$agex = htmlentities($res['age']);
$output .= "<tr>".
"<td><a href='?id=$idx'>$idx</a></td>".
"<td>$first</td>".
"<td>$last</td>".
"<td>$agex</td>".
"</tr>";
}
$output .= "</table>";
echo "$output";
$dbconn = null;
?>
</body>
</html>
Som du ser är den här koden så gott som identisk
med vår tidigare kod som skriver ut innehållet i en tabell i
en htmltabell.
Men observera det är en skillnad:
<a
href='?id=$idx'>$idx</a>
Den här raden skapar en länk till samma fil som tar emot de variabelnamn och dess värden som ska föras
över från aktuell sida till den samma sida via anropet anger enligt GET-metoden
i formulär, jämför $_POST[] tidigare. Obserera för att
skriva citationstecken " skriver vi \", annars om vi bara skriver
" så tolkar serverns php-interpretator detta som en del av php-skriptet.
Vi vill skicka över allt innehåll från en databastabellrad,
dvs en post i tabellen, så att vi lätt kan modifiera innehållet.
Formuläret är ju i princip identiskt med det som
vi skapade för lägga till poster. Det enda intressanta är
att vi i input-taggarna lägger till egenskapen value="..."
och sätter det värdet med hjälp av php och variablerna samt
värden som fördes över från den tidigare sidan.
Man ska kanske nämna också att id-värdet är ju inget
som ska kunna ändras därför placeras det i ett gömt(hidden)
fält i formuläret så att det förs över till nästa
sida som ska uppdatera informationen i databastabellen.
Ett alternativ till modifiera med GET är att modifiera med POST, vi får då ändra den första modifierafilen genom att lägga till en knapp i slutet på raden. Enklast är då också att lägga formtaggar runt knappen och baka in några hidden-fält som innehåller den information som ska skickas vidare.
Filen som tar emot informationen måste sen givetvis justeras med hänsyn till att informationen skickas via POST och inte GET. Dvs byta GET mot POST.
Nu tillbaks det ursprungliga spåret. Nu ska vi ta hand om informationen som vi modifierat.
Det enda nya här är databaskommandot på denna
rad:
$sql = "UPDATE pdodemotable SET firstname=?, lastname=?, age=? WHERE id=?";
Först så använder vi UPDATE och sätter
tabellfälten till de värden som förts hit till sidan och
för att göra det på rätt tabellrad så använder
vi WHERE id=?.
Del 5 - Ta bort en rad från en databastabell
Att ta bort är enkelt. Vi väljer tabellrad som ska tas bort och sen tar vi bort raden.
<!-- deletepost.php -->
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>Delete</title>
</head>
<body>
<?php
include ('dbconnection.php');
$message = null;
$id = null;
if (isset($_POST['id']) && !empty($_POST['id'])) {
$id = $_POST['id'];
try {
# prepare
$sql = "DELETE FROM pdodemotable WHERE id=?";
$stmt = $dbconn->prepare($sql);
# the data we want to insert
$data = array($id);
# execute width array-parameter
$stmt->execute($data);
$message .= "<br />Record deleted successfully.<br />";
}
catch(PDOException $e)
{
$message .= $sql . "<br>" . $e->getMessage();
}
} else {
$message .= "<br />";
}
echo $message;
// Ouput table with all posts
/*** The SQL SELECT statement ***/
$sql = "SELECT * FROM pdodemotable";
$stmt = $dbconn->prepare($sql);
// fetch width column names, create a table
$data = array();
$stmt->execute($data);
$output = "<table><caption>En ostylad tabell!</caption>";
while ($res = $stmt->fetch(PDO::FETCH_ASSOC)) {
$idx = htmlentities($res['id']);
$first = htmlentities($res['firstname']);
$last = htmlentities($res['lastname']);
$agex = htmlentities($res['age']);
$output .= "<tr>".
"<td>$idx</td>".
"<td>$first</td>".
"<td>$last</td>".
"<td>$agex</td>".
"<td><form method='post' action=''>".
"<input type='hidden' name='id' value='$idx'>".
"<button type='submit'>Ta bort</button></form></td>".
"</tr>";
}
$output .= "</table>";
echo "$output";
$dbconn = null;
?>
</body>
</html>
Är det något du undrar över så titta
på förklaringen till modifiera-delen.
Jag använder här det andra alternativet med ett formulär med info och knapp på varje rad.
Så gott som allt i den här filen är bekant.
Det enda nya delete-kommandot till databasen. Kommandot tar bort en rad
i tabellen som matchar where-delen.
Del 6 - Ta bort hel tabell
Var försiktig med denna kod. Den bör inte ligga i menyn för det är inte kul att av misstag råka ta bort en tabell full med data. Det kan dock nu när vi lär oss vara enklast att ta bort hela tabellen och börja om med att skapa en ny tabell med lite nya fräscha data.
<!-- deletetable.php -->
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>Create</title>
</head>
<body>
<?php
include ('dbconnection.php');
try {
// sql to delete table
$sql = "DROP TABLE IF EXISTS pdodemotable";
//use exec() because no results are returned
$dbconn->exec($sql);
echo "Table deleted successfully";
}
catch(PDOException $e)
{
echo $sql . "<br>" . $e->getMessage();
}
//Rensa kopplingen till databasen
$dbconn = null;
?>
</body>
</html>
Detta var grunderna i PHP-PDO-MySQL. Hoppas du får en enkel start och kan gå vidare i kurslitteraturen (eller via internet) när du vill utveckla ännu mer.
Lycka till!
Källor, referenser, bra länkar
Wikipedia: PHP
w3schools.com/php/php_mysql_intro.asp
phpro.org
hashphp.org