Databaseadgang fra PHP

Siden bogen PHP og MySQL udkom, er der kommet et nyt plug-in, som er bedre og sikrere, når man tilgår databaser fra PHP. Derfor anbefaler vi, at du bruger dette plugin i stedet for det, der er beskrevet i bogen. Det nye plug-in hedder MySQLi, hvor i’et står for improved.

Forbindelse til MySQL

Første trin i den proces er at oprette en forbindelse til MySQL-databasen fra PHP.  Det sker ved hjælp af funktionen at lave et nyt mysqli-objekt.

Når du laver objektet, skal du give fire parametre med. Det første er navn eller IP-adresse på den server, databasen kører på. På de fleste mindre websteder vil databasen køre på samme server som webserveren, og adressen vil derfor være localhost eller IP-nummeret 127.0.0.1.

Funktionens næste to parametre er brugernavn og adgangskode til at logge på databasen. Det er de samme, som vi angav, da vi oprettede databasebrugeren.  Den sidste parameter er navnet på den database, der skal åbnes.

Returværdien fra mysqli-funktionen er en identifikation af databaseforbindelsen. Den skal vi bruge som parameter til de funktioner, der skal bruge databaseforbindelsen.

Hvis noget går galt

I eksemplerne i dette kapitel regner vi med, at tingene går godt. Det er det taknemmelige ved eksempler. I den virkelige verden opstår der helt andre problemer.

Hvis du får en fejl fra MySQL – fordi databaseserveren ikke er tilgængelig, hvis der er en fejl i din SQL eller alt muligt andet – kan du få fejlbeskeden fra MySQL frem ved at kalde funktionen mysqli_error.

 

Eksempel 1.1 viser, hvordan der kan oprettes forbindelse til vores eksempler-database fra forrige kapitel via PHP.

 

<?php

  $forbindelse = new mysqli ("localhost", "test", "123qwert", "eksempler");

  mysql_select_db("eksempler");

 

  echo "Databaseforbindelse oprettet.";

?>

 

Lukning af databaseforbindelse

I mange programmeringssprog skal man være meget omhyggelig med at lukke sine databaseforbindelser igen, da man ellers risikerer, at de bliver ved med at være åbne og bruge ressourcer.

I PHP er det ikke nødvendigt. PHP lukker automatisk dine forbindelser, når det script, som åbnede dem, bliver afsluttet.

Skulle du få lyst til at lukke databaseforbindelsen før tid, kan du gøre det ved at kalde funktionen mysqli_close og give referencen til databaseforbindelsen med som parameter.

Når forbindelsen til databasen er på plads, kan vi begynde at sende forespørgsler; indsætte data, hente data og så videre. Vi starter med at se, hvordan vi indsætter data.

SQL Injection

Når hackere angriber et websted, er SQL Injection en hyppig fremgangsmåde. En SQL Injection foretages ved at ændre en af parametrene til SQL-forespørgslen, så forespørgslen gør noget helt andet end tiltænkt.

Forestil dig en tilsyneladende harmløs SQL-forespørgsel, som i PHP ser således ud:

 

$sql = "SELECT navn FROM brugere WHERE brugernavn = ’ " . _REQUEST["brugernavn"] . "’; ";

 

Det brugernavn, der skal søges efter, kommer ind som parameter fra en brugerindtastning. Forestil dig, at brugeren i stedet for et brugernavn skriver denne linje:

 

’; drop table brugere;

 

Når MySQL skal udføre kommandoen, vil den opfatte det som to kommandoer. Den første henter navn fra databasen – den anden sletter tabellen brugere. Med tilpas snilde er det muligt at hente brugernavne og adgangskoder ud af databasen eller at opgradere sin egen bruger til superrettigheder ved hjælp af SQL Injection.

For at undgå SQL Injection benytter vi i eksemplerne her kun prepared statements, som er en bestemt type databaseforespørgsler, der er sikret mod SQL injection.

Indsættelse af data

Data indsættes som bekendt med SQL-kommandoen Insert Into, som blev beskrevet tidligere i bogen.

Hvis vi vil indsætte data i tabellen adresser, kan det gøres med det PHP-script, der er vist i eksempel 1.2.

 

<?php

$forbindelse = new mysqli("localhost", "test", "123qwert", "eksempler");

 

 

$sql = "insert into adresser values ('Jens Hansen', 'Ved kæret 4', 7430, 'Ikast', '75869700');";

$statement = mysqli_prepare($sql);

 

mysqli_stmt_execute($statement);

echo "Data sat ind.";

?>

 

I eksemplet lægger vi først SQL-forespørgslen over i variablen sql. Det er ikke strengt nødvendigt, men gør koden lidt lettere at læse.

Eksemplet her er simpelt, fordi vi har hele SQL-forespørgslen i en streng. Hvis vi vil indsætte værdier, vi henter fra brugerens input, skal vi indsætte spørgsmålstegn, de steder brugerens værdier skal indsættes. Vil vi lade brugeren selv indtaste sin adresse vil udtrykket i stedet se således ud:

$statement = mysqli_prepare("insert into adresser values (?, ?, ?, ?, ?)");

Inden vi kalder mysql_stmt_execute skal vi fortælle, hvilke reelle værdier der skal indsættes. Det gør vi med funktionen mysqli_stmt_bind_param. Første parameter til funktionen er databaseforbindelse, anden parameter datatypen på de variable der skal indsættes, og de efterfølgende parametre afspejler, de værdier, der skal sættes ind. Datatypen kan være S for tekst, I for tal eller D for dato.

For at tilføje indsendte data fra en formular, kan PHP-koden se således ud:

$statement->bind_param("ssdss",

$_REQUEST['navn'],

$_REQUEST['adresse'],

$_REQUEST['postnummer'],

$_REQUEST['by'],

$_REQUEST['telefon']

);

 

Hentning af data

Når vi skal hente data fra databasen, bruger vi også prepared statements. Blot udnytter vi her, at mysqli_stmt_execute-funktionen faktisk returnerer en værdi, hvis SQL-forespørgslen henter data. Med funktionen mysqli_stmt_fetch  kan vi hente et array, der repræsenterer den næste række i resultatet.

Funktionen returnerer meget belejligt falsk, når der ikke er flere rækker i resultatet, og det gør den perfekt til brug i en while-løkke.

Array’et indeholder en variabel for hver kolonne i resultatet. Variablerne er navngivet efter kolonnenavnene, så det er let at finde de rette værdier.

Eksempel 1.3 viser, hvordan navne og adresser kan hentes fra databasen og præsenteres i en tabel.

 

 

<?php

  $forbindelse = new mysqli("localhost", "test", "123qwert", "eksempler");

 

  $sql = "SELECT navn, adresse, postnummer, bynavn FROM adresser";

  $statement = mysqli_prepare($sql);

  mysqli_stmt_execute($statement);

 

 

  echo "<table>";

  while ($post = mysql_stmt_fetch ($statemnt)) {

    echo "<tr>";

    echo "<td>" . $post['navn'] . "</td>";

    echo "<td>" . $post['adresse'] . "</td>";

    echo "<td>" . $post['postnummer'] . " " . $post['bynavn'] . "</td>";

    echo "</tr>";

  }

  echo "</table>";

?>

 

I eksemplet er det værd at lægge mærke til den lidt specielle konstruktion i while-sætningen. I en og samme linje tildeler vi en ny værdi til post-variablen, og tester om den er sand eller falsk. På den måde kan vi på samme tid få opdateret post-variablen og teste, om indholdet af while-løkken skal køres igen.