Wróć do informacji o e-podręczniku Wydrukuj Pobierz materiał do PDF Pobierz materiał do EPUB Pobierz materiał do MOBI Zaloguj się, aby dodać do ulubionych Zaloguj się, aby skopiować i edytować materiał Zaloguj się, aby udostępnić materiał Zaloguj się, aby dodać całą stronę do teczki

Współczesne techniki współpracy witryny z bazą danych

W tym e‑materiale poznamy cztery współczesne, istotne usprawnienia algorytmu komunikacji skryptu PHP z bazą danych.

  • Umieszczenie danych konfiguracyjnych połączenia w zewnętrznym pliku, możliwym do wywołania w pozostałych skryptach komunikujących się z bazą danych.

  • Obsługa wyjątków try .. catch zamiast „twardego” zatrzymania wykonania skryptu funkcją or die().

  • Wariant obiektowy współpracy z bazą danych (zamiast klasycznej wersji proceduralnej), w tym nowa metoda fetchowania obiektowego o nazwie fetch_object().

  • Wykorzystanie pętli typu foreach do przetwarzania rezultatów wyszukiwania w bazie.

Znajomość tych metod jest ważna z punktu widzenia optymalizacji tworzonych kodów źródłowych. Omówimy zatem nie tylko sposób wdrożenia tych metod, lecz także logiczne przyczyny wprowadzenia usprawnień i wynikające z nich konsekwencje – zarówno dla programisty webowego, jak i użytkownika tworzonej witryny.

Umieszczenie danych dostępowych do bazy w zewnętrznym pliku

Pierwszym etapem realizowania skryptu współpracującego z bazą danych MySQL jest zawsze podanie informacji dostępowych potrzebnych do nawiązania połączenia z bazą. Początkowo w skryptach zazwyczaj dokonujemy tego, używając danych dostępowych jako argumentów zapisanych wprost wewnątrz funkcji mysqli_connect():

Linia 1. $c znak równości mysqli podkreślnik connect otwórz nawias okrągły cudzysłów localhost cudzysłów przecinek cudzysłów root cudzysłów przecinek cudzysłów cudzysłów przecinek cudzysłów nazwa podkreślnik bazy cudzysłów zamknij nawias okrągły średnik.

Jednak w przypadku tworzenia całych witryn, a więc wielu skryptów realizujących w aplikacji przeróżne zadania, wielokrotne powtarzanie tych danych dostępowych wydaje się nieoptymalne. W przypadku konieczności zmiany konfiguracji serwisu (na przykład wskutek przeniesienia na inny serwer) jesteśmy zmuszeni poprawić dane dostępowe w każdym skrypcie osobno.

Ciekawostka

Jeżeli podczas przenoszenia witryny na inny serwer dojdzie do przeoczenia konieczności wprowadzenia zmian w którymkolwiek z wielu plików, powstanie serwis internetowy, w którym poprawnie działa tylko wybrana część skryptów (a my w ogóle nie będziemy o tym wiedzieć). Konieczność testowania każdej funkcjonalności osobno okaże się zadaniem wyjątkowo czasochłonnym.

Współcześnie postępujemy więc inaczej: opis aktu nawiązania połączenia oraz wszystkie dane dostępowe umieszczamy w specjalnie wydzielonym, zewnętrznym pliku. W razie konieczności dokonania zmian w danych dostępowych poprawki aplikujemy tylko w jednym skrypcie, zamiast w wielu rozproszonych zasobach. Specjalnie utworzony, dodatkowy plik możemy nazwać np. connect.php. Oto jego przykładowa zawartość:

Linia 1. otwórz nawias ostrokątny znak zapytania php. Linia 2. prawy ukośnik prawy ukośnik Konfiguracja dostępu do bazy danych. Linia 3. $host znak równości cudzysłów localhost cudzysłów średnik. Linia 4. $user znak równości cudzysłów root cudzysłów średnik. Linia 5. $pass znak równości cudzysłów cudzysłów średnik. Linia 6. $db znak równości cudzysłów nazwa podkreślnik bazy cudzysłów średnik. Linia 7. znak zapytania zamknij nawias ostrokątny.

Następnie w każdym skrypcie PHP, w którym łączymy się z bazą danych, użyjemy instrukcji jednokrotnego żądania specjalnego pliku:

Linia 1. otwórz nawias ostrokątny znak zapytania php. Linia 2. require podkreślnik once cudzysłów connect kropka php cudzysłów średnik. Linia 3. znak zapytania zamknij nawias ostrokątny.

W ten sposób dane konfiguracyjne zostaną „podpięte” we wszystkich potrzebnych dokumentach. Jest to idea znana z technologii CSS – style elementów witryny również przenosimy do zewnętrznego arkusza, aby w razie chęci dokonania zmian uniknąć wprowadzania dużej liczby poprawek w wielu miejscach jednocześnie.

Ciekawostka

Testowanie współpracy z bazą danych również staje się dzięki opisanej technice łatwe: wystarczy sprawdzenie jednego ze skryptów korzystających z bazy. Wiele współczesnych frameworków przestrzega tzw. podejścia DRYzasada DRYpodejścia DRY, umieszczając kluczowe informacje konfiguracyjne w zewnętrznym pliku. W przypadku popularnego systemu Wordpress jest to zasób o nazwie wp‑config.php.

Przyczyny oraz sposób implementacji zewnętrznego pliku zostały także przedstawione w filmie zawartym w sekcji „Film samouczek”.

Obsługa wyjątków: try .. catch

Instrukcję takiej postaci stosujemy współcześnie zamiast klasycznej obsługi błędów komunikacji z bazą danych z użyciem funkcji or die(). Tak zwane wyłapywanie wyjątków pozwala dużo elastyczniej reagować na poszczególne problemy w aplikacji webowej, zamiast po prostu „zabijać” wykonanie skryptu.

Używając instrukcji try, podejmujemy próbę nawiązania połączenia z bazą; w razie wystąpienia problemów (gdy kod błędu jest inny niż zero) dokonujemy tzw. rzucenia wyjątku. Korzystamy przy tym z zapisu throw new Exception. Taki wyjątek, mający unikalny identyfikator, można później „złapać” w specjalnej sekcji catch:

Linia 1. otwórz nawias ostrokątny znak zapytania php. Linia 2. try otwórz nawias klamrowy. Linia 3. $c znak równości mysqli podkreślnik connect otwórz nawias okrągły cudzysłów localhost cudzysłów przecinek cudzysłów root cudzysłów przecinek cudzysłów cudzysłów przecinek cudzysłów nazwa podkreślnik bazy cudzysłów zamknij nawias okrągły średnik. Linia 5. if otwórz nawias okrągły $c minus zamknij nawias ostrokątny connect podkreślnik errno wykrzyknik znak równości 0 zamknij nawias okrągły otwórz nawias klamrowy. Linia 6. throw new Exception otwórz nawias okrągły mysqli podkreślnik connect podkreślnik errno otwórz nawias okrągły zamknij nawias okrągły zamknij nawias okrągły średnik. Linia 7. zamknij nawias klamrowy. Linia 9. zamknij nawias klamrowy catch otwórz nawias okrągły Exception $error zamknij nawias okrągły otwórz nawias klamrowy. Linia 10. echo apostrof Błąd bazy danych dwukropek apostrof kropka $error minus zamknij nawias ostrokątny getMessage otwórz nawias okrągły zamknij nawias okrągły średnik. Linia 11. zamknij nawias klamrowy. Linia 12. znak zapytania zamknij nawias ostrokątny.

W profesjonalnych aplikacjach webowych przetworzeniem obiektu o nazwie $error można się zająć za pomocą specjalnie napisanych własnych funkcji (a w przypadku zastosowania technik obiektowych używając metod, czyli funkcji zdefiniowanych wewnątrz klas). Kod błędu pobiera metoda o nazwie mysqli_connect_errno(), wywołana już w momencie rzucania wyjątku. Wewnątrz sekcji catch dostęp do tego kodu uzyskujemy dzięki metodzie getMessage() wywołanej na rzecz obiektu $error

Wykrycie błędu, połączone z unikatową reakcją na jego rodzaj (osiąganą za sprawą identyfikatora numerycznego), daje możliwość zaprogramowania inteligentnej reakcji skryptu na problemy z komunikacją z serwerem. Nie musimy już zwyczajnie „zabijać” dalszego przetwarzania dokumentu – możemy użytkownika ostrzec, przekierować albo wyświetlić zawartość zastępczą. Współczesne zaawansowane aplikacje internetowe zapewniają internaucie właśnie taką „miękką” reakcję na kłopoty z bazą danych, zamiast brutalnie uniemożliwiać przeglądanie witryny.

Użycie konstrukcji try .. catch zazwyczaj łączymy z pierwszą opisaną techniką, czyli z przeniesieniem aktu nawiązania połączenia z bazą do zewnętrznego pliku. Więcej szczegółów na temat zrealizowania obsługi połączenia w taki sposób podajemy w filmie samouczku.

Wariant obiektowy współpracy witryny z bazą danych

We współczesnym programowaniu wyróżniamy dwa podstawowe paradygmaty, czyli przyjęte konwencje budowania aplikacji. W podejściu proceduralnymprogramowanie proceduralnepodejściu proceduralnym stosujemy funkcje, czyli wydzielone fragmenty kodu, które realizują konkretne zadania. Konwencja obiektowaprogramowanie obiektoweKonwencja obiektowa jest bardziej abstrakcyjna i złożona, gdyż używamy obiektów skonstruowanych na bazie szablonów zwanych klasami. Każdy obiekt ma przypisane pewne atrybuty (zmienne) oraz metody (funkcje zdefiniowane wewnątrz klas, a służące do przetwarzania zmiennych).

Programowanie zorientowane obiektowo jest trudniejsze do zrozumienia, jednak to właśnie za sprawą rozbudowanej struktury logicznej zapewnia utrzymanie porządku w kodzie, chroni dane przed niepożądanym nadpisaniem (dzięki tzw. hermetyzacji), a ponadto ułatwia rozbudowę aplikacji (tzw. skalowanie). Współpraca witryny z bazą danych za pośrednictwem biblioteki mysqli także może zostać zrealizowana obiektowo.

Nawiązanie połączenia z bazą danych

W wersji obiektowej pojawia się dodatkowa klauzula new, która tworzy nowy obiekt o nazwie $c. Metoda mysqli() to tzw. konstruktor obiektu. Kolejność argumentów wewnątrz nawiasów okrągłych pozostaje w obu wariantach identyczna.

wersja proceduralna

wersja obiektowa

$c = mysqli_connect(...);

$c = new mysqli(...);

Obsługa polskich znaków

Podobnie jak w wersji proceduralnej, odpowiednią linię kodu umieszczamy już po nawiązaniu aktywnego połączenia. Tym razem jednak zapis ma następującą postać: obiekt->metoda("argument");

wersja proceduralna

wersja obiektowa

mysqli_set_charset($c,"utf8");

$c->set_charset("utf8");

Wykonanie zapytania SQL

Zakładamy, że treść kwerendy do wykonania została uprzednio umieszczona w pomocniczej zmiennej $q.

wersja proceduralna

wersja obiektowa

$result = mysqli_query($c, $q);

$result = $c->query($q);

Pobranie liczby zwróconych rekordów

W tym przypadku mamy do czynienia nie z metodą obiektu, tylko z jego atrybutem o nazwie num_rows (zwróć uwagę na brak nawiasów okrągłych, właściwych zapisowi metody):

wersja proceduralna

wersja obiektowa

$ile = mysqli_num_rows($result);

$ile = $result->num_rows;

Fetchowanie pojedynczych rekordów

W poprzednich e‑materiałach poznaliśmy trzy sposoby fetchowania rekordów do tablicy jednowymiarowej:

  • mysqli_fetch_row()przetwarzanie liczbowe – ponumeruj (od zera) szufladki tablicy jednowymiarowej;

  • mysqli_fetch_assoc()wyjmowanie asocjacyjne (skojarzeniowe) – ponazywaj słownie szufladki tablicy jednowymiarowej, nadając im zawsze taki sam identyfikator, jaki mają kolumny w bazie danych;

  • mysqli_fetch_array()przetwarzanie równocześnie numeryczne i asocjacyjne (dostępne są oba rodzaje indeksów).

Zapis obiektowy tych metod (tutaj na przykładzie przetwarzania liczbowego) wygląda następująco:

Linia 1. $c znak równości mysqli podkreślnik connect otwórz nawias okrągły cudzysłów localhost cudzysłów przecinek cudzysłów root cudzysłów przecinek cudzysłów cudzysłów przecinek cudzysłów nazwa podkreślnik bazy cudzysłów zamknij nawias okrągły średnik. Linia 2. $q znak równości cudzysłów SELECT asterysk FROM tabela cudzysłów średnik. Linia 3. $result znak równości $c minus zamknij nawias ostrokątny query otwórz nawias okrągły $q zamknij nawias okrągły średnik. Linia 5. while otwórz nawias okrągły $row znak równości $result minus zamknij nawias ostrokątny fetch podkreślnik row otwórz nawias okrągły zamknij nawias okrągły zamknij nawias okrągły otwórz nawias klamrowy. Linia 6. echo $row otwórz nawias kwadratowy 0 zamknij nawias kwadratowy średnik. Linia 7. zamknij nawias klamrowy.

Dla każdej z trzech klasycznych metod pozbywamy się przedrostka mysqli_ występującego w nazwie instrukcji, a ponadto $result nie jest już argumentem funkcji, tylko obiektem umieszczonym po lewej stronie operatora: ->.

Na rzecz obiektu $result wywołujemy metodę fetch_row(), która kopiuje do tablicy jednowymiarowej pojedynczy rekord. W bieżącym e‑materiale poznamy jeszcze możliwość przetwarzania rekordów nową, czwartą metodą o nazwie fetch_object().

Fetchowanie obiektowe fetch_object

Podejście obiektowe umożliwia także przetwarzanie rekordów nie w postaci tablic jednowymiarowych, lecz obiektów mających atrybuty:

Linia 1. $c znak równości mysqli podkreślnik connect otwórz nawias okrągły cudzysłów localhost cudzysłów przecinek cudzysłów root cudzysłów przecinek cudzysłów cudzysłów przecinek cudzysłów nazwa podkreślnik bazy cudzysłów zamknij nawias okrągły średnik. Linia 2. $q znak równości cudzysłów SELECT login przecinek email FROM users cudzysłów średnik. Linia 4. if otwórz nawias okrągły $result znak równości $c minus zamknij nawias ostrokątny query otwórz nawias okrągły $q zamknij nawias okrągły zamknij nawias okrągły otwórz nawias klamrowy. Linia 5. while otwórz nawias okrągły $obj znak równości $result minus zamknij nawias ostrokątny fetch podkreślnik object otwórz nawias okrągły zamknij nawias okrągły zamknij nawias okrągły otwórz nawias klamrowy. Linia 6. echo $obj minus zamknij nawias ostrokątny login średnik. Linia 7. echo $obj minus zamknij nawias ostrokątny email średnik. Linia 8. zamknij nawias klamrowy. Linia 9. zamknij nawias klamrowy.

Obiekt o nazwie $obj nada atrybuty noszące nazwy takie same, jak kolumny w tabeli bazy danych. Zamiast podawania indeksów tablicy z użyciem nawiasów kwadratowych, stosujemy w tym przypadku zapis obiekt->atrybut.

Ciekawostka

Idea przechowywania atrybutów wydobytych z bazy danych wewnątrz obiektów, a nie tablic, stała się bardzo rozpowszechniona w wielu współczesnych frameworkach webowych. Warto więc jak najszybciej przyzwyczaić się do takiego modelu fetchowania rekordów – czas na to poświęcony zwróci się później z nawiązką.

Zwolnienie pamięci zajmowanej przez rekordy

Kolejnym logicznym usprawnieniem działania skryptu współpracującego z bazą danych jest zwolnienie pamięci zajmowanej przez wyjęte rekordy. Oczywiście może to nastąpić dopiero w momencie, gdy dane znajdujące się w $result nie są już w skrypcie dłużej potrzebne. Takie wyczyszczenie pamięci ma największy sens w skryptach wykonujących wiele zapytań, a generujących duże liczby zwracanych rekordów.

wersja proceduralna

wersja obiektowa

mysqli_free_result($result);

$result->free_result();

Zamknięcie połączenia z bazą danych

Na rzecz obiektu $c reprezentującego nawiązane połączenie wywołujemy metodę o nazwie close(). W tym przypadku argument staje się zbędny, gdyż po lewej stronie operatora -> znajduje się już informacja, które z istniejących połączeń zamierzamy zakończyć:

wersja proceduralna

wersja obiektowa

mysqli_close($c);

$c->close();

Wykorzystanie pętli foreach

Tego typu instrukcja iteracyjna upraszcza wizualnie klasyczny zapis fetchowania rekordów. Nagłówek pętli jest dużo prostszy w porównaniu do analogicznej instrukcji while. Po lewej stronie operatora as znajduje się obiekt $result klasy mysqli_result, przechowujący wszystkie wyjęte z bazy rekordy. Natomiast po prawej stronie tego operatora znajduje się pomocnicza, jednowymiarowa tablica $row, w której komórkach umieszczamy atrybuty pojedynczego rekordu.

Linia 1. $c znak równości mysqli podkreślnik connect otwórz nawias okrągły cudzysłów localhost cudzysłów przecinek cudzysłów root cudzysłów przecinek cudzysłów cudzysłów przecinek cudzysłów nazwa podkreślnik bazy cudzysłów zamknij nawias okrągły średnik. Linia 2. $q znak równości cudzysłów SELECT login przecinek email FROM users cudzysłów średnik. Linia 3. $result znak równości $c minus zamknij nawias ostrokątny query otwórz nawias okrągły $q zamknij nawias okrągły średnik. Linia 5. foreach otwórz nawias okrągły $result as $row zamknij nawias okrągły otwórz nawias klamrowy. Linia 6. echo $row otwórz nawias kwadratowy cudzysłów login cudzysłów zamknij nawias kwadratowy średnik. Linia 7. echo $row otwórz nawias kwadratowy cudzysłów email cudzysłów zamknij nawias kwadratowy średnik. Linia 8. zamknij nawias klamrowy.
Ciekawostka

Zapis as (ang. „jako”) możemy logicznie potraktować tak samo, jak znany z języka SQL operator o identycznej nazwie, stosowany w kwerendach – jest to przecież logicznie nowy alias właśnie fetchowanego rekordu.

Słownik

programowanie obiektowe
programowanie obiektowe

konwencja projektowania oprogramowania zalecająca traktowanie programu komputerowego jako współpracujących ze sobą abstrakcyjnych obiektów, mających pewne atrybuty (określające stan) oraz metody (funkcje definiujące zachowania); obiekty skonstruowane na podstawie szablonów (klas) współpracują ze sobą w celu wykonywania określonych zadań

programowanie proceduralne
programowanie proceduralne

konwencja projektowania oprogramowania zalecająca dzielenie instrukcji na realizujące konkretne zadania funkcje lub procedury (funkcje zwracają wartość, zaś procedury nie); program komputerowy traktujemy jako zbiór współpracujących ze sobą funkcji, wymieniających między sobą wartości nieglobalne

zasada DRY
zasada DRY

(od ang. Don't Repeat Yourself – „nie powtarzaj się”) reguła projektowania oprogramowania, która zaleca unikanie stosowania tych samych fragmentów kodów źródłowych (lub bardzo zbliżonych) w wielu miejscach; lepszą praktyką jest wyodrębnienie powtarzającego się fragmentu z ewentualnym zastąpieniem wartości parametrami i jedynie odwoływanie się do niego w licznych wystąpieniach