Współpraca mysqli z bazą (wariant proceduralny)

Mirosław Zelent

Opiszmy teraz kolejne kroki implementacji połączenia z bazą danych przy użyciu rozszerzenia mysqli w wariancie proceduralnym (czyli paradygmacie opartym na funkcjach). Najprościej mówiąc: każdej charakterystycznej czynności odpowiada specjalnie przygotowana funkcja, której użycie sprowadza się najczęściej jedynie do podania właściwych parametrów wejściowych.

Nawiązanie połączenia

Połączenie z bazą danych nawiązujemy z użyciem funkcji mysqli_connect() podając dane dostępowe wprost w funkcji:

$conn = mysqli_connect("localhost", "root", "", "szkola");

Lub umieszczamy te dane w zmiennych zdefiniowanych w zewnętrznym pliku, osadzając go przed połączeniem instrukcją require_once (patrz poprzedni artykuł). Nazwy zmiennych znajdują się w wywołaniu i ich nazwy muszą być takie same jak w pliku dbconnect.php.

require_once "dbconnect.php";
$conn = mysqli_connect($host, $user, $pass, $db);

Obsługa polskich znaków

Już po nawiązaniu połączenia, włączamy obsługę standardu utf8 dla przesyłanych danych z użyciem funkcji mysqli_set_charset(). Argumentami funkcji są kolejno: identyfikator połączenia (tutaj $conn) oraz nazwa zestawu znaków (tutaj "utf8"). Zwróćmy uwagę: w MySQL zapisujemy nazwę standardu bez myślnika (inaczej niż w HTML, gdzie myślnik występuje).

mysqli_set_charset($conn, "utf8");

Wykonanie zapytania SQL

Kolejnym krokiem jest zdefiniowanie treści zapytania SQL, które mamy zamiar wykonać na naszej bazie danych. Treść kwerendy zostaje umieszczona w pomocniczej zmiennej (tutaj noszącej nazwę $q nawiązującej do angielskiego słowa "query"). Jednak rzeczywiste wykonanie kwerendy odbywa się dopiero w momencie wywołania funkcji mysqli_query(). Argumentami funkcji są kolejno: identyfikator połączenia (tutaj $conn) oraz treść zapytania (tutaj przechowywana w pomocniczej zmiennej $q):

$q = "SELECT id, nazwa FROM klasa";
$result = mysqli_query($conn, $q) or die("Problemy z odczytem danych!");

Ponieważ wykonywanym w przykładzie zapytaniem jest SELECT, to zwrócone przez bazę rekordy zostają włożone do zmiennej $result (zwróćmy uwagę, że dla np. kwerendy INSERT nie ma takiej potrzeby, bo wówczas baza nie "odpowiada" rekordami). Ponadto, jako że wykonanie zapytania może się zwyczajnie nie udać (chociażby dlatego, że jest niepoprawne składniowo albo nie mamy uprawnień do wykonania danego rodzaju kwerendy), to pojawia się zapis or die(), co tłumaczymy prosto jako "lub umrzyj" :) Stąd gdy kwerendy nie uda się wykonać, dzięki funkcji die() skrypt zostanie "zabity", a na stronie pojawi się komunikat zapisany w przesyłanym w nawiasie argumencie.

Uwaga! Czasami zdarzy się, iż częścią zapytania będzie ciąg znaków podany przez użytkownika w formularzu - jako przykład niech posłuży takie zapytanie:

$klasa = $_POST["klasa"]; // wartość pobrana z formularza
$q = "SELECT id FROM klasa WHERE nazwa='$klasa'";

W takim przypadku istnieje spore ryzyko wykonania takiego zapytania, gdyż użytkownik o złych intencjach może spróbować "wstrzyknąć" nam SQL w naszą predefiniowaną kwerendę poprzez tę zmienną, której treść sam przecież definiuje w formularzu. I jakkolwiek podczas egzaminu w technikum zazwyczaj nie wymaga się obecnie zabezpieczenia skryptu przed tego typu atakiem (nazywanym SQL injection), to warto być świadomym natury tego zagrożenia. Po dokładne wyjaśnienie jak poradzić sobie ze wstrzykiwaniem SQL udaj się do filmu zrealizowanego w drugim odcinku serii PHP.

Wstrzykiwanie SQL
(ang. SQL injection) - metoda ataku witryny internetowej, polegająca na przemyceniu fragmentu zapytania SQL poprzez odpowiednio spreparowaną wartość wprowadzaną w formularzu. Atak zadziała tylko w przypadku niedostatecznej tzw. sanityzacji (oczyszczania) pobranej od usera wartości

Pobranie ilości zwróconych rekordów

Dzięki funkcji mysqli_num_rows() istnieje możliwość odczytania liczby zwróconych przez zapytanie SELECT rekordów (co w niektórych zastosowaniach może okazać się przydatne). W analizowanym w tym artykule przykładzie, wynik kwerendy został zapisany pod nazwą $result, stąd taki jest argument funkcji przesłany do mysqli_num_rows(). W pomocniczej zmiennej $ile znajdzie się liczba zwróconych rekordów, natomiast bezwzględnie należy pamiętać, aby tę linię umiejscowić w kodzie pod wywołaniem mysqli_query(), nigdy powyżej - to logiczne.

$result = mysqli_query($conn, $q) or die("Problemy z odczytem danych!");
$ile = mysqli_num_rows($result);

Fetchowanie pojedynczych rekordów

Angielskie słowo fetch oznacza: sprowadzić, przynieść, wydobyć. Doskonale oddaje ono proces wyjmowania pojedynczych rekordów z całej chmury zwróconych zapytaniem danych, umieszczonych w $result. Pomocnicza zmienna $row zawiera zawsze jeden, pojedynczy rekord (tablicę jednowymiarową, wiersz) wyjęty ze wszystkich rezultatów kwerendy. Oczywiście to wyjmowanie do $row musi być realizowane w pętli (bo rekordów może być dużo). W poniższym przykładzie jest to while() wykonujący się dopóki istnieją rekordy do wyjęcia (pętla sama się przerwie, gdy wszystkie rekordy zostaną obsłużone).

$q = "SELECT id, nazwa FROM klasa";
$result = mysqli_query($conn, $q) or die("Problemy z odczytem danych!");
while($row = mysqli_fetch_row($result))
{
echo $row[1]."<br>";
// wartość $row[1] wypisze nazwę klasy,
// gdyby było $row[0] to wypisalibyśmy jej id
}

Wyróżniamy trzy podstawowe rodzaje fetchowania rekordów do tablicy jednowymiarowej, tutaj mającej nazwę $row:

  • mysqli_fetch_row() - wyjmowanie liczbowe - ponumeruj (od zera) szufladki tablicy jednowymiarowej;
  • mysqli_fetch_assoc() - wyjmowanie asocjacyjne (czyli skojarzeniowe) - ponazywaj słownie szufladki tablicy jednowymiarowej, nadając im zawsze taką samą nazwę, jaką noszą kolumny w bazie danych;
  • mysqli_fetch_array() - zarówno ponumeruj jak i ponazywaj szufladki tablicy jednowymiarowej (wada: redundancja danych - każda szufladka jest "podwójna", gdyż istnieje zarówno komórka zaindeksowana numerycznie jak i słownie).

Przykład fetchowania asocjacyjnego:

$q = "SELECT id, nazwa FROM klasa";
$result = mysqli_query($conn, $q) or die("Problemy z odczytem danych!");
while($row = mysqli_fetch_assoc($result))
{
echo $row['id']."<br>";
// wartość $row['nazwa'] wypisze nazwę klasy
}

Zamknięcie połączenia z bazą

Brak linii zamykającej połączenie z bazą danych może spowodować utratę punktów na egzaminie - nie zapomnijmy dokonać tego w odpowiednim miejscu kodu, po wszystkich wykonanych bazodanowych czynnościach! Argumentem funkcji mysqli_close() jest identyfikator zamykanego połączenia:

mysqli_close($conn);