Skrypt PHP, który łączy się z localhost jako root bez hasła z bazą egzamin i na końcu zamyka połączenie. Funkcje mysqli ze ściągi CKE, wiersze jako lista i jako tabela, dane z formularza w klauzuli WHERE, skrypt JavaScript zmieniający kolory strony. Lekcja 13.4 kursu INF.03.
Ta lekcja składa skrypty wymagane przez arkusz, czyli ostatni z pięciu ocenianych rezultatów, „skrypt połączenia z bazą", oraz tę część rezultatu „działanie witryny internetowej", która zależy od kodu. Robi się to na końcu zadania, gdy baza jest już zaimportowana, a strona i styl stoją. Cztery skrypty wracają w arkuszach niemal bez zmian: dwa wypisują wiersze z bazy według wzoru, trzeci bierze dane z formularza, czwarty zmienia w JavaScripcie wygląd całej strony. Teoria samych funkcji jest w lekcji o PHP i bazie danych oraz w lekcji o modelu DOM, tutaj liczy się kolejność ruchów i miejsca, w których rezultat przepada. Połączenie, które arkusz opisuje dosłownie
Wymagania połączenia arkusz wypisuje zdanie po zdaniu i za każdym razem brzmią tak samo: skrypt „napisany w języku PHP", „łączy się z serwerem bazodanowym na localhost, użytkownik root bez hasła, baza danych o nazwie egzamin", a „na końcu działania skrypt zamyka połączenie z serwerem". Nazwa bazy bywa inna, bo bierze się z treści zadania, ale adres, użytkownik i puste hasło są stałe, tak samo jak zamknięcie połączenia w ostatnim wierszu.
<?php
$polaczenie = mysqli_connect('localhost', 'root', '', 'egzamin');
if (!$polaczenie) {
die('Blad polaczenia z baza');
}
$wynik = mysqli_query($polaczenie, 'SELECT nazwa, miasto, cena FROM nocleg');
if (!$wynik) {
die(mysqli_error($polaczenie));
}
while ($w = mysqli_fetch_array($wynik)) {
echo '<li>' . $w['nazwa'] . '</li>';
}
mysqli_close($polaczenie);
Czwarty parametr mysqli_connect wybiera bazę od razu. Drugi dopuszczalny zapis to połączenie z trzema parametrami i osobne mysqli_select_db($polaczenie, 'egzamin'), obie wersje są w tabeli dołączonej do arkusza. Puste apostrofy na trzecim miejscu to konto bez hasła i nie wolno ich zamienić na słowo root.
Arkusz dokłada do zadania tabelę „Wybór funkcji języka PHP do obsługi bazy MySQL i MariaDB", więc nazw nie trzeba pamiętać co do znaku. Trzeba natomiast wiedzieć, co która robi.
Funkcja z tabeli arkusza
Co robi
mysqli_connect
otwiera połączenie z serwerem bazy
mysqli_select_db
wybiera bazę na otwartym połączeniu
mysqli_query
wysyła jedno zapytanie SQL
mysqli_fetch_row
pobiera kolejny wiersz z numerami kolumn od zera
mysqli_fetch_array
pobiera kolejny wiersz z numerami i nazwami kolumn
mysqli_num_rows
podaje liczbę wierszy wyniku
mysqli_num_fields
podaje liczbę kolumn wyniku
mysqli_error
oddaje komunikat o błędzie ostatniej operacji
mysqli_close
zamyka połączenie z serwerem
To są nazwy proceduralne i tego stylu warto trzymać się przez całe zadanie. Wersja obiektowa (new mysqli, $polaczenie->query) działa tak samo, ale jej nazw arkusz nie podaje, więc każdą literówkę w metodzie trzeba wyłapać samodzielnie, bez ściągi na biurku. Z tego samego powodu w pętli lepiej postawić mysqli_fetch_array niż mysqli_fetch_assoc: druga funkcja jest poprawna, ale w tabeli arkusza jej nie ma.
Wszystkie skrypty PHP z zadania siedzą zwykle w jednym pliku, na przykład noclegi.php, w miejscach wyznaczonych przez układ strony. Można otworzyć jedno połączenie na początku i zamknąć je jednym mysqli_close na końcu dokumentu albo dać każdemu skryptowi własną parę, byle każde otwarcie miało swoje zamknięcie. Prościej sprawdzić to drugie: liczba wywołań mysqli_connect ma się zgadzać z liczbą wywołań mysqli_close.
Skrypt 1 i 2: wiersze jako lista i jako wiersze tabeli
Pierwsze dwa skrypty robią to samo, tylko w innych znacznikach. Arkusz podaje wzór jednej pozycji, na przykład „nazwa noclegu, miasto, cena zł", i wynik ma wyglądać dokładnie tak, razem z przecinkami i jednostką.
<?php
$polaczenie = mysqli_connect('localhost', 'root', '', 'egzamin');
$wynik = mysqli_query($polaczenie, 'SELECT nazwa, miasto, cena FROM nocleg');
echo '<ul>';
while ($w = mysqli_fetch_array($wynik)) {
echo '<li>' . $w['nazwa'] . ', ' . $w['miasto'] . ', ' . $w['cena'] . ' zl</li>';
}
echo '</ul>';
mysqli_close($polaczenie);
Hotel Pod Lipa, Zakopane, 180 zl
Pensjonat Widok, Zakopane, 140 zl
Willa Nad Potokiem, Szczyrk, 210 zl
Znaczniki <ul> i </ul> stoją poza pętlą, bo lista jest jedna, a powtarzają się wyłącznie pozycje. Gdy zapytanie nic nie znajdzie, pętla nie wykona się ani razu i zostanie pusta lista, dlatego przed nią sprawdza się mysqli_num_rows($wynik).
Drugi skrypt wypełnia wiersze tabeli. Sam znacznik <table> z wierszem nagłówkowym jest już w kodzie strony, skrypt dokłada wyłącznie <tr> z komórkami. Wygodniejsza jest tu mysqli_fetch_row, bo numery odpowiadają kolejności kolumn z SELECT. <?php
$polaczenie = mysqli_connect('localhost', 'root', '', 'egzamin');
$wynik = mysqli_query($polaczenie, 'SELECT nazwa, miasto FROM nocleg ORDER BY nazwa');
while ($w = mysqli_fetch_row($wynik)) {
echo '<tr><td>' . $w[0] . '</td><td>' . $w[1] . '</td></tr>';
}
mysqli_close($polaczenie);
Sortowanie i warunki należą do zapytania, nie do PHP: kolejność bierze się z ORDER BY, a zawężenie wyniku z WHERE, jak w lekcji o zapytaniu SELECT. Skrypt ma tylko przepisać wiersze do znaczników. Pułapka: jedno wywołanie funkcji fetch daje jeden wiersz. Wywołana raz, poza pętlą, wypisze wyłącznie pierwszy rekord i tabela zostanie prawie pusta.
Skrypt 3: wartość z formularza w klauzuli WHERE
Trzeci skrypt czyta pole formularza wysłanego metodą POST do tej samej strony i wstawia jego wartość do warunku zapytania. Sam formularz opisuje lekcja o formularzach HTML, a odbiór danych lekcja o formularzach w PHP. Klucz w tablicy $_POST to wartość atrybutu name pola, nie jego etykieta. <form method="post" action="noclegi.php">
<input type="number" name="cena" min="0">
<input type="submit" value="Szukaj">
<input type="reset" value="Wyczysc">
</form>
<?php
if (isset($_POST['cena'])) {
$max = (int) $_POST['cena'];
$polaczenie = mysqli_connect('localhost', 'root', '', 'egzamin');
$sql = "SELECT nazwa, miasto, cena FROM nocleg WHERE cena <= $max";
$wynik = mysqli_query($polaczenie, $sql);
while ($w = mysqli_fetch_array($wynik)) {
echo '<li>' . $w['nazwa'] . ', ' . $w['cena'] . ' zl</li>';
}
mysqli_close($polaczenie);
}
Warunek isset pilnuje, żeby strona otwarta po raz pierwszy, jeszcze przed wysłaniem formularza, nie próbowała czytać nieistniejącego klucza i nie wypisała ostrzeżenia nad układem strony. Wartość liczbowa wchodzi do zapytania bez apostrofów, tekstowa wymaga ich wokół siebie: WHERE miasto = '$miasto'. Rzutowanie (int) nic nie kosztuje, a odcina wpisanie w pole fragmentu zapytania.
Skrypt 4: JavaScript zmieniający kolory całej strony
Czwarty skrypt działa po stronie klienta i uruchamia go przycisk na stronie. Zadanie brzmi zwykle tak: po kliknięciu zmieniają się kolory tła i czcionki całej witryny, „np. poprzez dołączenie nowego arkusza stylów". Pola i metody, których do tego trzeba, są w drugiej ściądze arkusza, „Wybrane pola i metody modelu DOM języka JavaScript".
Zapis ze ściągi arkusza
Co robi
document.getElementById("x")
oddaje element o identyfikatorze x
document.getElementsByTagName("p")
oddaje kolekcję elementów danego znacznika
document.getElementsByClassName("c")
oddaje kolekcję elementów danej klasy
element.innerHTML
treść elementu razem ze znacznikami
element.setAttribute("href", "styl_2.css")
ustawia wartość atrybutu
element.style.property
ustawia pojedynczą właściwość stylu
document.createElement("link")
tworzy nowy element, jeszcze poza drzewem
rodzic.appendChild(element)
dopina element jako ostatnie dziecko
onclick, onload, onkeyup
zdarzenia uruchamiające funkcję
Prostsza droga to ustawienie właściwości na elemencie body, czyli na przodku wszystkich widocznych elementów strony. Nazwy właściwości w JavaScripcie nie mają minusa, drugi człon zaczyna się wielką literą.
function zmienKolory() {
document.body.style.backgroundColor = "Tomato";
document.body.style.color = "Maroon";
}
<input type="button" value="Zmien kolory" onclick="zmienKolory()">
Druga droga, ta z cytatu, dokłada do sekcji head nowy element link wskazujący drugi arkusz stylów przygotowany wcześniej. Nazwę tego pliku podaje arkusz, w przykładzie styl_2.css.
function dolaczStyl() {
var arkusz = document.createElement("link");
arkusz.setAttribute("rel", "stylesheet");
arkusz.setAttribute("href", "styl_2.css");
document.getElementsByTagName("head")[0].appendChild(arkusz);
}
Obsługę kliknięcia wpisuje się atrybutem onclick albo przypisuje w kodzie, co pokazuje lekcja o zdarzeniach. Nazwa funkcji w przycisku musi zgadzać się co do znaku z nazwą w definicji, bo przy pomyłce przycisk nie robi nic, a ślad po błędzie zostaje tylko w konsoli przeglądarki. Funkcja może stać w znaczniku <script> w tym samym pliku albo w osobnym pliku dołączonym tym samym znacznikiem z atrybutem src. Arkusz zwykle zostawia to do wyboru, a wymaga działającego przycisku. Definicja musi zostać wczytana, zanim ktoś kliknie, więc bezpieczne miejsce to koniec sekcji body, tuż przed jej zamknięciem.
Uruchomienie i sprawdzenie działania
Plik .php musi leżeć w katalogu htdocs serwera XAMPP i zostać otwarty adresem http://localhost/noclegi.php. Otwarty podwójnym kliknięciem z dysku nie wykona się wcale: przeglądarka pokaże kod albo pustą stronę, bo PHP wykonuje serwer, nie ona. W XAMPP Control Panel muszą działać obie usługi, Apache i MySQL, co opisuje lekcja o środowisku. Gotowe pliki zapisuje się w folderze o nazwie numeru PESEL, razem z resztą wyników, według dyscypliny plików z pierwszej lekcji działu. Rezultat „działanie witryny internetowej" ocenia się z otwartej strony, nie z kodu: lista i tabela mają być wypełnione danymi z bazy, formularz po wysłaniu ma wrócić z zawężonym wynikiem, a przycisk ma zmienić kolory. Sam kod bez połączenia z bazą sprawdza się w interpreterze PHP i w interpreterze JavaScript w przeglądarce, a same zapytania w placu zabaw SQL w przeglądarce. Gdzie traci się punkty
›
Brak mysqli_close na końcu skryptu: zamknięcie połączenia arkusz wymienia jako osobne wymaganie.
›
Hasło inne niż puste albo nazwa bazy wymyślona zamiast wziętej z treści zadania.
›
Wzór wypisu odtworzony niedokładnie: brak jednostki, inny przecinek, kolumny w innej kolejności niż we wzorze.
›
Znaczniki <ul> albo <table> wypisywane w pętli, przez co powstaje tyle list, ile jest wierszy.
›
if zamiast while przy pobieraniu wierszy albo fetch wywołany raz, poza pętlą.
›
Odczyt przez $_GET, gdy arkusz wymaga metody POST, albo klucz inny niż atrybut name pola.
›
Brak isset i ostrzeżenie PHP wypisane nad układem strony przy pierwszym otwarciu.
›
Polskie znaki jako pytajniki: dokłada się wtedy mysqli_set_charset($polaczenie, 'utf8') zaraz po połączeniu.
›
Zapis background-color w JavaScripcie zamiast backgroundColor, bo wersja z minusem to nazwa z CSS, nie z DOM.
›
Zmiana koloru jednego akapitu zamiast całej strony: kolory ustawia się na body albo nowym arkuszem stylów.
›
document.write wywołane po wczytaniu strony, które czyści cały dokument razem z układem.
›
Skrypt w sekcji head sięgający po element, którego przeglądarka jeszcze nie wczytała, bez zdarzenia onload.
›
Plik zapisany poza folderem o nazwie numeru PESEL albo pod inną nazwą niż podana w arkuszu.
Ściąga
mysqli_connect('localhost', 'root', '', 'egzamin')
serwer, użytkownik, puste hasło, baza
mysqli_select_db($p, 'egzamin')
wybór bazy na otwartym połączeniu
mysqli_query($p, $sql)
wysyła zapytanie, oddaje wynik SELECT
mysqli_fetch_array($wynik)
wiersz z numerami i nazwami kolumn
mysqli_fetch_row($wynik)
wiersz z numerami kolumn od zera
mysqli_num_rows($wynik)
liczba wierszy wyniku
mysqli_num_fields($wynik)
liczba kolumn wyniku
mysqli_error($p)
komunikat o błędzie ostatniej operacji
mysqli_close($p)
zamknięcie połączenia, ostatni wiersz skryptu
mysqli_set_charset($p, 'utf8')
ratunek na polskie znaki jako pytajniki
while ($w = mysqli_fetch_array($wynik))
pętla po wszystkich wierszach wyniku
echo '<li>' . $w['nazwa'] . '</li>';
jedna pozycja listy z jednego wiersza
echo '<tr><td>' . $w[0] . '</td></tr>';
jeden wiersz tabeli z jednego wiersza wyniku
$_POST['cena']
wartość pola o atrybucie name="cena"
isset($_POST['cena'])
sprawdzenie, czy formularz został wysłany
WHERE cena <= $max
liczba w warunku, bez apostrofów
WHERE miasto = '$miasto'
tekst w warunku, w apostrofach
document.body.style.backgroundColor
kolor tła całej strony
document.body.style.color
kolor czcionki całej strony
document.createElement("link")
nowy element arkusza stylów
document.getElementsByTagName("head")[0]
sekcja head z kolekcji
rodzic.appendChild(element)
dopięcie elementu do drzewa
<input type="button" onclick="f()">
przycisk uruchamiający funkcję
http://localhost/noclegi.php
jedyny poprawny sposób otwarcia pliku PHP
Pobierz ściągę PDF