5. Współpraca z bazą danych MySQL

advertisement
mgr inż. Grzegorz Kraszewski – TECHNOLOGIE INTERNETOWE 3 – wykład 5: „Współpraca z MySQL”.
5. Współpraca z bazą danych MySQL
5.1. Informacje ogólne
Język PHP posiada obsługę wielu relacyjnych baz danych, jedną z najpopularniejszych
jest baza MySQL. PHP pozwala na pełną współpracę z bazą. Praca polega na otwarciu
sesji, zadaniu zapytania, lub zapytań, odebraniu ewentualnych wyników i na koniec
zamknięciu sesji. Obsługa MySQL jest zewnętrznym modułem i trzeba ją włączyć przy
kompilacji PHP (zwłaszcza PHP 5). Rzecz jasna PHP obsługuje zarówno połączenia z
lokalną bazą danych (znajdującą się na tym samym serwerze co wykonywany skrypt),
jak i z bazami zdalnymi, za pomocą protokołu TCP/IP.
5.2. Nawiązanie połączenia – mysql_connect()
Za pomocą tej funkcji tworzymy nowe połączenie z bazą danych:
$polaczenie = mysql_connect(host[:port], uzytkownik, haslo);
Wszystkie parametry funkcji są opcjonalne. Pierwszy parametr to nazwa, lub adres IP
serwera na którym znajduje się baza. Domyślną nazwą jest „localhost”, domyślnym
portem 3306. Następnie mamy nazwę użytkownika bazy, wartością domyślną jest nazwa
użytkownika procesu wykonującego skrypt (najczęściej będzie to „httpd”), po nim hasło
tego użytkownika, wartością domyślną jest pusty łańcuch tekstowy. Wynikiem funkcji
jest wartość typu zasób identyfikująca połączenie (to ważne, jeżeli w skrypcie
mgr inż. Grzegorz Kraszewski – TECHNOLOGIE INTERNETOWE 3 – wykład 5: „Współpraca z MySQL”.
wykonujemy więcej niż jedno połączenie). W przypadku niepowodzenia zwracana jest
wartość logiczna FALSE.
5.3. Użycie operatora die i operatora @ przy obsłudze błędów
Przy łączeniu się z bazą danych stosunkowo często zdarzają się niepowodzenia. Błędy
takie wymagają prawidłowej obsługi, w przeciwnym wypadku dostarczamy potencjalnym
hakerom przydatnich informacji. Oto prosty przykład:
$c = mysql_connect('jakis.serwer.com.pl:9384', 'httpd', 'tajne_haslo');
W przypadku niepowodzenia połączenia, użytkownik w przeglądarce zobaczy taki oto
tekst:
Warning: mysql_connect(): Unknown MySQL Server Host 'jakis.serwer.com.pl' (0) in /
home/krashan/public_html/t.php on line 9
Albo na przykład coś takiego (dla innego serwera):
Warning: mysql_connect(): Access denied for user: 'httpd@localhost' (Using password:
YES) in /home/krashan/public_html/t.php on line 9
Na szczęście hasło nie jest podawane, ale sporo informacji wycieka (np. lokalizacja
skryptu, serwer na którym jest baza, nazwa użytkownika). Nie powinniśmy dopuścić do
mgr inż. Grzegorz Kraszewski – TECHNOLOGIE INTERNETOWE 3 – wykład 5: „Współpraca z MySQL”.
pokazania takich informacji użytkownikowi. Do ich zablokowania użyjemy operatorów die
i @. Drugi z nich, jak wiadomo, blokuje wypisywanie wiadomości o błędach, jednak
jakąś wiadomość dobrze by było wyświetlić, żeby użytkownik mniej więcej wiedział
gdzie jest problem. Tui możemy posłużyć się operatorem die, który po wypisaniu
wskazanej wiadomości powoduje natychmiastowe zakończenie skryptu. Oto przykładowe
zastosowanie:
$c = @mysql_connect('jakis.serwer.com.pl:9384', 'httpd', 'tajne_haslo') or
die "Problem z połączeniem z bazą danych!";
Tym razem jedyne, co użytkownik zobaczy na ekranie w przypadku nienawiązania
połączenia, będzie napis:
Problem z połączeniem z bazą danych!
Nie ujawniamy więc żadnych informacji potencjalnym włamywaczom. Kilka słów
wyjaśnienia na temat zastosowanego operatora or. W przypadku dwóch wyrażeń
połączonych tym operatorem, PHP najpierw ewaluuje (a więc wykonuje) najpierw
pierwsze z nich, w tym przypadku łączy się z bazą danych. Jeżeli wynik tego wyrażenia
konwertuje się do logicznej prawdy, drugie wyrażenie nie jest wykonywane (bo TRUE or
cokolwiek = TRUE). Jeżeli zaś pierwsze wyrażenie ma wartość FALSE, to wykonywane
jest drugie, bo jego wartość jest niezbędna do ustalenia wartości całego wyrażenia.
Zatem die() wykona się tylko jeśli mysql_connect() zwróci FALSE.
mgr inż. Grzegorz Kraszewski – TECHNOLOGIE INTERNETOWE 3 – wykład 5: „Współpraca z MySQL”.
5.4. Zamykanie połączenia z bazą – mysql_close()
Tutaj mamy sytuację podobną jak przy plikach. W zasadzie nie jesteśmy zobligowani do
zamykania sesji MySQL, ponieważ zostają one zamknięte automatycznie przy wyjściu ze
skryptu. Niemniej jednak wskazane jest (ze względu na oszczędne gospodarowanie
zasobami) zamykanie połączenia, gdy nie jest ono już potrzebne. Oto przykład
zamknięcia połączenia:
mysql_close($polaczenie);
Gdzie $polaczenie to oczywiście identyfikator zwrócony przez mysql_connect(). Można
też wywołać tę funkcję bez parametru, wtedy zamykane jest ostatnio otwarte połączenie.
Jest to wygodne, gdy w skrypcie jest tworzone tylko jedno połączenie.
5.5. Wybór bazy danych – mysql_select_db()
Tak jak i przy pracy z klientem MySQL, pierwszym krokiem przy pracy jest wybór bazy
na której będziemy pracować:
mysql_select_db('nazwa');
Oczywiście użytkownik, którego podaliśmy przy nawiązywaniu połączenia, musi mieć
dostęp do wybranej bazy. Ewentualne błędy z tym związane uwidocznią się dopiero przy
wysłaniu zapytania, jako że mysql_select_db() nie zwraca żadnej wartości.
mgr inż. Grzegorz Kraszewski – TECHNOLOGIE INTERNETOWE 3 – wykład 5: „Współpraca z MySQL”.
5.6. Wysyłanie zapytań – mysql_query()
Funkcja ta służy do wysyłania wszelkiego rodzaju zapytan do bazy, zarówno tych
odczytujących informacje, jak i tych modyfikujących. Dozwolony jest cały repertuar
języka SQL (PHP nie sprawdza zapytania pod względem składniowym ani
merytorycznym). Wynik funkcji zależy od rodzaju zapytania. W przypadku zapytań
zwracających informację (przede wszystkim SELECT, a także SHOW, DESCRIBE i
EXPLAIN), wynikiem jest zmienna typu zasób używana później do pobierania informacji
ze zwróconej odpowiedzi. Dla zapytań modyfikujących, takich jak UPDATE, DROP czy
DELETE zwracana jest wartość logiczna TRUE. W przypadku niepowodzenia, dla
wszystkich zapytań zwracane jest logiczne FALSE. Przykład użycia:
if ($odp = mysql_query('SELECT * FROM tablica WHERE id = 46'))
{
// rób coś z odpowiedzią
mysql_free_result($odp);
}
Przyczyną wielu błędów przy tej funkcji jest niepoprawne ustawienie praw użytkowników
w bazie danych, oczywiście użytkownik podany przy otwieraniu połączenia musi mieć
uprawnienia do zadawania używanych w mysql_query() typów zapytań.
mgr inż. Grzegorz Kraszewski – TECHNOLOGIE INTERNETOWE 3 – wykład 5: „Współpraca z MySQL”.
5.7. Zwalnianie wyników zapytania – mysql_free_result()
Zapytania kierowane do bazy danych często zwracają sporą ilość informacji. Wykonując
funkcję mysql_query() PHP rezerwuje pamięć na wszystkie podawane przez bazę danych
informacje. Mająz na względzie oszczędne gospodarowanie zasobami serwera (przede
wszystkim wolną pamięcią) powinno się zwalniać odpowiedź na zapytanie w chwili, gdy
nie jest już potrzebna. Jeżeli tego nie zrobimy, zrobi to za nas PHP, ale dopiero przy
wyjściu ze skryptu. Jedynym parametrem mysql_free_result() jest zasób zwrócony
uprzednio przez mysql_query(). Jeżeli nie podamy tego parametru zostanie zwolniony
wynik ostatniego zapytania (zwracającego dane). Przykład użycia tej funkcji znajduje się
w rozdziale 5.6.
5.8. Ogólne informacje o wykonanym zapytaniu
Funkcja mysql_num_rows() zwraca ilość wierszy danych znajdujących się w odpowiedzi
na zapytanie SELECT, SHOW, czy DESCRIBE. Parametrem tej funkcji jest identyfikator
odpowiedzi zwrócony przez mysql_query().
Funkcja mysql_affected_rows() podaje ilość wierszy tablicy w bazie danych
zmodyfikowanych przez zapytania takie jak UPDATE, DELETE, czy DROP.
mgr inż. Grzegorz Kraszewski – TECHNOLOGIE INTERNETOWE 3 – wykład 5: „Współpraca z MySQL”.
5.9. Sposoby pobierania informacji z zapytania
Wynik zapytania zwrócony przez mysql_query(), jest zwykle tablicą złożoną z wybranych
przez zapytanie danych. Nie jest on jednak tablicą z punktu widzenia PHP, wszak rezultat
zapytania jest typu zasób. PHP pozwala na sięganie do odpowiedzi z bazy całymi
wierszami, bądź też dostęp do pojedynczych pól.
5.9.1. mysql_fetch_row()
To najczęściej używana funkcja czytająca jeden wiersz odpowiedzi. Z wiersza tego
tworzona jest tablica, której kolejne elementy o kluczach 0, 1, 2... zawierają wartości z
kolejnych kolumn tableli SQL wybranych zapytaniem. Załóżmy, że mamy następującą
tabelę w MySQL:
imie
nazwisko
wiek
varchar(20)
varchar(30)
smallint(3)
Wyślijmy teraz zapytanie:
$w = mysql_query('SELECT * FROM tabela');
mysql_fetch_row() zwróci nam taką tablicę:
mgr inż. Grzegorz Kraszewski – TECHNOLOGIE INTERNETOWE 3 – wykład 5: „Współpraca z MySQL”.
0 => [imie]
1 => [nazwisko]
2 => [wiek]
Teraz inne nieco zapytanie:
$w = mysql_query('SELECT wiek, imie FROM tabela');
Tablica zwracana przez mysql_fetch_row() wygląda teraz inaczej:
0 => [wiek]
1 => [imie]
Po zwróceniu aktualnego wiersza odpowiedzi, następuje przejście do następnego. Jeżeli
więc będziemy wywoływać mysql_fetch_row() w pętli, to dostaniemy tablice zawierające
kolejne wiersze tabeli zwróconej przez zapytanie. W momencie dotarcia do końca tabeli,
funkcja zwróci FALSE.
5.9.2. mysql_fetch_assoc()
Funkcja podobna do poprzedniej, z tym, że kluczami zwracanej tablicy są nazwy kolumn
z SQL-a (ewentualnie zmienione w zapytaniu). Przy założeniu, że operujemy na tabeli
SQL jak w punkcie 5.9.1, poniższe zapytania dadzą odpowiedzi jak pokazano:
mysql_query('SELECT * FROM tabela');
mgr inż. Grzegorz Kraszewski – TECHNOLOGIE INTERNETOWE 3 – wykład 5: „Współpraca z MySQL”.
'imie' => [imie]
'nazwisko' => [nazwisko]
'wiek' => [wiek]
Przykład zapytania ze zmianą nazw kolumn:
$w = mysql_query('SELECT wiek AS latka, imie AS cokolwiek FROM tabela');
Tablica zwracana przez mysql_fetch_assoc() wygląda w tym przypadku tak:
'latka' => [wiek]
'cokolwiek' => [imie]
Tak samo jak dla mysql_fetch_row(), po zwróceniu aktualnego wiersza odpowiedzi,
następuje przejście do następnego.
5.9.3. mysql_result()
Ta z kolei funkcja pozwala na dostęp do pojedynczego pola tabeli zwróconej w
odpowiedzi na zapytanie. Generalnie jest ona wolniejsza od poprzednich, więc jeżeli
przetwarzamy całe wiersze danych, nie jest zalecana. Zawsze lepiej jest ograniczyć
zakres danych w zapytaniu do bazy, niż w samym skrypcie PHP. Dzięki temu mniej
danych jest przesyłanych z bazy do skryptu, zmniejszamy też zużycie pamięci.
Ograniczenie zakresu danych w skrypcie jest usprawiedliwione tylko wtedy, gdy
kryterium jest na tyle skomplikowane, że trudno je zapisać w zapytaniu SQL.
mgr inż. Grzegorz Kraszewski – TECHNOLOGIE INTERNETOWE 3 – wykład 5: „Współpraca z MySQL”.
Funkcja mysql_result() przyjmuje trzy parametry. Pierwszy to identyfikator odpowiedzi
na zapytanie, zwrócony przez mysql_query(). Drugi to numer wiersza, a trzeci,
opcjonalny to numer, albo nazwa kolumny (domyślnie pierwsza kolumna). Funkcja działa
szybciej, jeżeli podamy numer kolumny zamiast nazwy. Oto przykład pokazujący
niewłaściwe użycie mysql_result() i prawidłowy sposób ograniczenia zakresu danych w
samym zapytaniu. Poszukujemy w tabeli opisanej w punkcie 5.9.1 nazwisk wszystkich
osób o imieniu Jan i wieku poniżej 40 lat:
$q = mysql_query('SELECT * FROM tabela') or die ('Błąd!');
for ($i = 0; $i < mysql_num_rows($q); $i++)
{
if ((mysql_result($q, $i, 'imie') == 'Jan') and (mysql_result($q, $i,
'wiek') < 40))
{
echo(mysql_result($q, $i, 'nazwisko'));
echo('<br>');
}
}
A teraz tak, jak to powinno być zrobione:
$q = mysql_query("SELECT nazwisko FROM tabela WHERE imie=\"Jan\" AND
wiek<40") or die ('Błąd!');
while ($wiersz = mysql_fetch_row($q)) print("{$wiersz[0]}<br>");
mgr inż. Grzegorz Kraszewski – TECHNOLOGIE INTERNETOWE 3 – wykład 5: „Współpraca z MySQL”.
5.10. Pomijanie danych – mysql_data_seek()
Jedyną do tej pory poznaną funkcją pozwalającą na przeskakiwanie nieinteresujących
danych, była nienajszybsza mysql_result(). Przy pracy całymi wierszami na swobodne
przesuwanie się po wierszach tabeli pozwala mysql_data_seek(). Oto sposób użycia:
mysql_data_seek($wynik, $wiersz);
Wskaźnik danych w wyniku identyfikowanym przez $wynik zostaje przesunięty do
wiersza o numerze $wiersz. Jeżeli podany wiersz nie istnieje, funkcja zwróci FALSE.
Następne wywołanie mysql_fetch_row() lub mysql_fetch_assoc() załaduje podany
wiersz. Jeszcze raz podkreślam, że zdecydowanie lepiej jest odrzucić niepotrzebne
wiersze już na poziomie zapytania do bazy danych (poprzez odpowiednie użycie słowa
kluczowego WHERE), niż ładować dużą tabelę i obrabiać ją w PHP.
5.11. Długości poszczególnych pól – mysql_fetch_lenghts()
Funkcja ta służy do pobrania długości (w znakach) pól ostatnio załadowanego (przy
pomocy mysql_fetch_row() lub mysql_fetch_assoc()) wiersza. Zwracana jest tablica z
kluczami numerycznymi, wartości odpowiadają długościom pól tabeli. Oto przykład, jeżeli
zwrócony przez mysql_fetch_assoc() wiersz wygląda tak:
'imie' => 'Władysław', 'nazwisko' => 'Gomułka', 'wiek' => 107
mgr inż. Grzegorz Kraszewski – TECHNOLOGIE INTERNETOWE 3 – wykład 5: „Współpraca z MySQL”.
to tablica zwrócona przez mysql_fetch_lenghts() będzie miała następującą postać:
0 => 9, 1 => 7, 2 => 3
Download