Przejdź do głównej treści
EE.09-04-21.06-SGCzerwiec 2021 · 42 kroki · ok. 83 min · 35 kryteriów z klucza

Rozwiązanie krok po kroku: Panel administratora portalu społecznościowego (Wersja podstawowa)

Panel administratora portalu społecznościowego: baza dane4 z tabelami osoby i hobby z pliku CKE, cztery zapytania (LIMIT, złączenie JOIN dla jednej osoby, funkcje AVG, MIN i MAX oraz UPDATE), zdjęcie wykadrowane do kwadratu 100 × 100 px oraz strona users.php z dwoma skryptami PHP: w bloku lewym lista użytkowników z wiekiem obliczonym z roku urodzenia, w bloku prawym karta osoby o identyfikatorze wpisanym w formularzu.

To arkusz EE.09 z czerwca 2021 - kwalifikacji formuły 2017, którą zastąpiła INF.03. W tej samej sesji był pokrewny arkusz EE.09-01-21.06 (lista przyjaciół): ma te same materiały - bazę osób z hobby i osiem zdjęć - ale inne zapytania, inną stronę i inny skrypt; jego rozwiązanie jest przy tamtym arkuszu. Kroki idą zdanie po zdaniu za treścią arkusza - przy każdym jest polecenie z arkusza, a kod pokazuje dokładnie te linie, które je spełniają. Skrypty są najpierw napisane najprościej, funkcjami mysqli z tabeli 1 arkusza, a na końcu sprawdzone na prawdziwym wstrzyknięciu SQL i zabezpieczone.

To jest wersja podstawowa. W zakładce „Nowoczesny kod (flex, PDO)” jest drugi sposób rozwiązania tego samego arkusza: flexbox zamiast float, etykieta formularza, PDO z zapytaniem przygotowanym na górze pliku i szablon z pętlą foreach - obie wersje są zgodne z kluczem.

Baza i zdjęcia pochodzą z oryginalnego archiwum CKE zad4.zip (załącznik do pobrania na stronie arkusza, hasło w treści zadania). Zapytania i zrzuty są policzone na MariaDB 10.4 - tej samej, która jest w XAMPP. Podgląd od kroków z PHP to wynik prawdziwego uruchomienia kodu w PHP 8.2 (klucz każe sprawdzać w XAMPP 7.4.8 - użyte funkcje działają w obu wersjach tak samo). Wiek w podglądzie jest liczony od roku 2026, dlatego jest wyższy niż na obrazie 2 w arkuszu, przygotowanym w 2019 roku.

Jak liczą się punkty. Klucz ma 35 kryteriów (R.1.1 - R.5.8), każde za 1 punkt. Próg zdania części praktycznej to 75%, czyli 27 punktów - można stracić 8 kryteriów i nadal zdać. Przy każdym kroku jest napisane, które kryteria spełnia; egzaminator ocenia spełnienie kryteriów z klucza, nie zgodność z tym kodem.

  1. Etap 1: Baza danych

    Kroki 1-7 · po tym etapie masz 6 z 35 kryteriów (pkt)

    Krok 1: Folder zdającego i archiwum zad4

    ok. 2 min
    Polecenie z arkusza

    Na pulpicie znajduje się archiwum ZIP o nazwie zad4.zip zabezpieczone hasłem: *Uzytkownicy^Portalu$ Należy utworzyć folder o nazwie odpowiadającej numerowi PESEL zdającego lub w przypadku jego braku innemu numerowi, którym został podpisany arkusz. Archiwum należy rozpakować do tego folderu.

    Na pulpicie tworzysz folder nazwany numerem PESEL - w tym rozwiązaniu w jego miejscu stoi imię i nazwisko autora, Bartosz Bryniarski. Archiwum zad4.zip otwierasz programem 7-Zip (albo innym programem do archiwów ZIP) i rozpakowujesz do tego folderu, podając hasło *Uzytkownicy^Portalu$ - z gwiazdką na początku i znakiem dolara na końcu. W środku jest plik dane.sql i osiem zdjęć: osoba1.jpg - osoba8.jpg.

    Pliki strony muszą leżeć w tym samym folderze co zdjęcia - skrypt wstawi nazwę zdjęcia z bazy bez żadnej ścieżki.

    Typowe błędy

    Pliki zapisane poza folderem zdającego (np. w htdocs bez kopii w folderze) nie trafią na płytę - a ocenia się tylko to, co jest na płycie.

  2. Krok 2: XAMPP i pusta baza dane4

    ok. 2 min
    Polecenie z arkusza

    Uruchom usługi MySQL i Apache za pomocą XAMPP Control Panel. Za pomocą narzędzia phpMyAdmin wykonaj podane operacje na bazie danych: Utwórz bazę danych o nazwie dane4

    W XAMPP Control Panel klikasz Start przy Apache i MySQL, potem w przeglądarce otwierasz http://localhost/phpmyadmin. Nowa w lewym panelu, nazwa dane4 (z cyfrą na końcu), Utwórz. Porównywanie napisów możesz zostawić domyślne - tabele z pliku i tak przyniosą własne kodowanie (latin1).

    Typowe błędy

    Baza dane (bez cyfry) to strata R.1.1 i R.5.1 - skrypt łączy się z bazą po nazwie, a klucz sprawdza nazwę dane4.

  3. Krok 3: Import pliku dane.sql i zrzut egzamin.jpg

    Kryteria:

    R.1.1 Wykonano import tabel do bazy danych dane4 , czynność udokumentowano plikiem o nazwie egzamin w formacie JPEG

    ok. 3 min
    Polecenie z arkusza

    Do bazy dane4 zaimportuj plik dane.sql z rozpakowanego archiwum. Wykonaj zrzut ekranu po imporcie. Zrzut zapisz w folderze z numerem PESEL lub w przypadku jego braku w folderze z innym numerem, którym został podpisany arkusz, w formacie JPEG i nazwij egzamin. Nie kadruj zrzutu. Powinien on obejmować cały ekran monitora, z widocznym paskiem zadań. Na zrzucie powinny być widoczne elementy wskazujące na poprawnie wykonany import tabel

    Zaznacz bazę dane4, karta Import, Wybierz plik → dane.sql, Wykonaj. Plik tworzy pięć tabel: hobby (16 rekordów), osoby (40 rekordów) oraz puste producenci, produkty i rodzaje - do zadania potrzebne są tylko dwie pierwsze.

    „Elementy wskazujące na poprawnie wykonany import” to zielony komunikat o sukcesie i lista tabel w lewym panelu albo na karcie Struktura bazy. Zrzut całego ekranu z paskiem zadań zapisujesz jako egzamin.jpg - w tym arkuszu w formacie JPEG, a zrzuty zapytań w PNG.

    Typowe błędy

    Ten zrzut ma nazwę egzamin i format JPEG. Wykadrowany zrzut albo zrzut bez paska zadań nie jest oceniany (uwaga w kluczu przy R.1).

    Podgląd strony po tym kroku
    Podgląd strony po kroku 3
  4. Krok 4: Zapytanie 1: pierwsze 30 osób

    Kryteria: ,

    R.1.2 Zapisano plik tekstowy o nazwie kwerendy zawierający co najmniej jedno zapytanie SQL, wynikające z treści zadania

    R.1.3 Utworzono zapytanie 1 wybierające jedynie pola id, imie, nazwisko, rok_urodzenia, zdjecie z tabeli osoby . Kwerenda wybiera początkowe 30 wierszy, jawnie wskazana liczba wierszy. W pliku z kwerendami lub na zrzucie istnieje zapis np.: SELECT id, imie, nazwisko, rok_urodzenia, zdjecie FROM osoby LIMIT 30; oraz wynik działania zapytania udokumentowano zrzutem, na którym widocznych jest dokładnie 30 rekordów jedynie pola id, imie, nazwisko, rok_urodzenia, zdjecie

    ok. 3 min
    Polecenie z arkusza

    Zapisz i wykonaj zapytania SQL działające na bazie dane4. Zapytania zapisz w pliku kwerendy.txt, w folderze z numerem PESEL lub w przypadku jego braku w folderze z innym numerem, którym został podpisany arkusz. Wykonaj zrzuty ekranu przedstawiające wyniki działania kwerend. Zrzuty zapisz w formacie PNG i nadaj im nazwy kw1, kw2, kw3, kw4. Zrzuty powinny obejmować cały ekran monitora z widocznym paskiem zadań. Zapytanie 1: wybierające jedynie pola id, imie, nazwisko, rok_urodzenia, zdjecie z tabeli osoby. Kwerenda wybiera pierwsze 30 wierszy, należy jawnie wskazać liczbę wierszy

    Zaznacz bazę dane4, karta SQL:

    • SELECT id, imie, nazwisko, rok_urodzenia, zdjecie - pięć kolumn z arkusza („jedynie” wyklucza SELECT *, które dołożyłoby Hobby_id i opis),
    • FROM osoby,
    • LIMIT 30 - jawnie wskazana liczba wierszy. Tabela ma 40 osób, a phpMyAdmin sam pokazuje 25 wierszy na stronę - dlatego limit musi stać w zapytaniu.

    Wynik: 30 rekordów, od id 2 (Monika Kowalska) do id 31 (Grzegorz Roh). Zapytanie kopiujesz do pliku kwerendy.txt, a cały ekran zapisujesz jako kw1.png - przy 30 wierszach przewiń wynik tak, żeby było widać komunikat „Pokazano wiersze 0 - 29 (30 łącznie)”. To zapytanie wyśle skrypt w bloku lewym.

    kwerendy.txt Tekst nowy plik
    -- Zapytanie 1
    SELECT id, imie, nazwisko, rok_urodzenia, zdjecie FROM osoby LIMIT 30;
    Podgląd strony po tym kroku
    Podgląd strony po kroku 4
  5. Krok 5: Zapytanie 2: dane osoby o id 10 z nazwą hobby

    Kryteria:

    R.1.4 Utworzono zapytanie 2 wybierające jedynie pola imie, nazwisko, rok_urodzenia, opis, zdjecie z tabeli osoby oraz odpowiadające im pole nazwa z tabeli hobby dla osoby o id równym 10. W pliku z kwerendami lub na zrzucie istnieje zapis np.: SELECT imie, nazwisko, rok_urodzenia, opis, zdjecie, nazwa FROM osoby JOIN hobby ON osoby.Hobby_id = hobby.id WHERE osoby.id = 10; możliwe INNER JOIN lub bez JOIN (porównanie kluczy w where) oraz wynik działania zapytania udokumentowano zrzutem, na którym widoczny jest dokładnie jeden rekord: Roksana Rybnik 1995 pozdrawiam osoba3.jpg biegi

    ok. 4 min
    Polecenie z arkusza

    Zapytanie 2: wybierające jedynie pola imie, nazwisko, rok_urodzenia, opis, zdjecie z tabeli osoby oraz odpowiadające im pole nazwa z tabeli hobby dla osoby o id równym 10

    • SELECT imie, nazwisko, rok_urodzenia, opis, zdjecie, nazwa - pięć kolumn z osoby i nazwa hobby z hobby,
    • FROM osoby JOIN hobby ON osoby.Hobby_id = hobby.id - złączenie: do osoby dołączany jest wiersz hobby o numerze z jej kolumny Hobby_id,
    • WHERE osoby.id = 10 - kolumna id jest w obu tabelach, więc trzeba wskazać tabelę.

    Wynik: jeden rekord - Roksana Rybnik, 1995, pozdrawiam, osoba3.jpg, biegi, dokładnie jak w kluczu. Zrzut: kw2.png. To zapytanie wyśle skrypt w bloku prawym, z identyfikatorem z formularza w miejscu liczby 10.

    Typowe błędy

    Samo WHERE id = 10 przy złączeniu kończy się błędem #1052 („Column 'id' in where clause is ambiguous”).

    kwerendy.txt Tekst zmienione: 3 linie
    -- Zapytanie 1
    SELECT id, imie, nazwisko, rok_urodzenia, zdjecie FROM osoby LIMIT 30;
    
    -- Zapytanie 2
    SELECT imie, nazwisko, rok_urodzenia, opis, zdjecie, nazwa FROM osoby JOIN hobby ON osoby.Hobby_id = hobby.id WHERE osoby.id = 10;
    Podgląd strony po tym kroku
    Podgląd strony po kroku 5
  6. Krok 6: Zapytanie 3: średni, najniższy i najwyższy rok urodzenia

    Kryteria:

    R.1.5 Utworzono zapytanie 3 liczące średni rok urodzenia oraz najniższy i najwyższy rok urodzenia z tabeli osoby . W pliku z kwerendami lub na zrzucie istnieje zapis np.: SELECT AVG(rok_urodzenia), MIN(rok_urodzenia), MAX(rok_urodzenia) FROM osoby; oraz wynik działania zapytania udokumentowano zrzutem, na którym widoczne są jedynie dane: 1992.7 1967 2009 (pierwsza wartość z dowolnym zaokrągleniem)

    ok. 2 min
    Polecenie z arkusza

    Zapytanie 3: liczące średni rok urodzenia oraz najniższy i najwyższy rok urodzenia z tabeli osoby

    Trzy funkcje agregujące w jednym SELECT: AVG(rok_urodzenia) - średnia, MIN(…) - najmniejsza wartość, MAX(…) - największa. Funkcja agregująca zamienia całą tabelę w jeden wiersz wyniku.

    Wynik: 1992.7000, 1967, 2009 - zgodnie z kluczem (1992,7 w dowolnym zaokrągleniu, najstarsza osoba urodziła się w 1967, najmłodsza w 2009). Zrzut: kw3.png.

    kwerendy.txt Tekst zmienione: 3 linie
    -- Zapytanie 1
    SELECT id, imie, nazwisko, rok_urodzenia, zdjecie FROM osoby LIMIT 30;
    
    -- Zapytanie 2
    SELECT imie, nazwisko, rok_urodzenia, opis, zdjecie, nazwa FROM osoby JOIN hobby ON osoby.Hobby_id = hobby.id WHERE osoby.id = 10;
    
    -- Zapytanie 3
    SELECT AVG(rok_urodzenia), MIN(rok_urodzenia), MAX(rok_urodzenia) FROM osoby;
    Podgląd strony po tym kroku
    Podgląd strony po kroku 6
  7. Krok 7: Zapytanie 4: nowy opis dla osób z hobby 4

    Kryteria:

    R.1.6 Utworzono zapytanie 4 aktualizujące pole opis z tabeli osoby dla osób, których pole Hobby_id jest równe 4. Wartość pola opis dowolna. W pliku z kwerendami lub na zrzucie istnieje zapis np.: UPDATE osoby SET opis="..." WHERE Hobby_id = 4; (dowolny wpis w miejscu kropek) oraz wynik działania zapytania udokumentowano zrzutem, na którym widoczny jest komunikat o poprawnie wykonanym zapytaniu lub tabela ze zmienionymi danymi

    ok. 2 min
    Polecenie z arkusza

    Zapytanie 4: aktualizujące pole opis z tabeli osoby dla osób, których pole Hobby_id jest równe 4. Wartość nowego wpisu w polu opis jest dowolna będąca możliwym hobby

    • UPDATE osoby - zmiana istniejących rekordów,
    • SET opis = 'akrobatyka' - nowa wartość pola; arkusz pozwala wpisać dowolne hobby,
    • WHERE Hobby_id = 4 - tylko osoby z hobby numer 4 (gimnastyka).

    W bazie jest jedna taka osoba - Anna Kowalska z id 25 - więc phpMyAdmin melduje 1 wiersz zmieniony. Zrzut: kw4.png (komunikat albo tabela ze zmienionym opisem). Plik kwerendy.txt ma komplet czterech zapytań.

    Typowe błędy

    UPDATE bez WHERE zmienia opis wszystkim 40 osobom - phpMyAdmin nie pyta o potwierdzenie, a cofnąć to można tylko ponownym importem.

    kwerendy.txt Tekst zmienione: 3 linie
    -- Zapytanie 1
    SELECT id, imie, nazwisko, rok_urodzenia, zdjecie FROM osoby LIMIT 30;
    
    -- Zapytanie 2
    SELECT imie, nazwisko, rok_urodzenia, opis, zdjecie, nazwa FROM osoby JOIN hobby ON osoby.Hobby_id = hobby.id WHERE osoby.id = 10;
    
    -- Zapytanie 3
    SELECT AVG(rok_urodzenia), MIN(rok_urodzenia), MAX(rok_urodzenia) FROM osoby;
    
    -- Zapytanie 4
    UPDATE osoby SET opis = 'akrobatyka' WHERE Hobby_id = 4;
    Podgląd strony po tym kroku
    Podgląd strony po kroku 7
  8. Etap 2: Grafika i strona HTML

    Kroki 8-24 · po tym etapie masz 18 z 35 kryteriów (pkt)

    Krok 8: Grafika: kadr 1:1 z twarzą

    ok. 2 min
    Polecenie z arkusza

    Plik osoba1.jpg, wypakowany z archiwum, skadrowany do proporcji 1:1, tak aby była widoczna twarz osoby.

    osoba1.jpg z archiwum ma 300 × 200 px - jest poziomy, a pozostałe zdjęcia są kwadratowe. W GIMP-ie narzędzie Zaznaczenie prostokątne z opcją Stała: proporcje 1:1, zaznaczenie 200 × 200 px (cała wysokość zdjęcia) przesunięte tak, żeby twarz była w środku - tutaj od x = 35 px - i Obraz → Przytnij do zaznaczenia. Podgląd pokazuje kadr przed skalowaniem.

    Typowe błędy

    Kadr z lewej krawędzi zdjęcia (x = 0) ucina twarz z prawej strony - klucz wymaga, żeby twarz była widoczna (R.2.1).

    Podgląd strony po tym kroku
    Podgląd strony po kroku 8
  9. Krok 9: Grafika: rozmiar dokładnie 100 × 100 px

    Kryteria:

    R.2.1 Plik osoba1.jpg zawiera widoczną twarz osoby, rozmiar zdjęcia dokładnie 100 px na 100 px

    ok. 2 min
    Polecenie z arkusza

    Przeskalowany do rozmiaru dokładnie 100 px na 100 px. Pozostałe pliki graficzne są przygotowane i nie należy ich zmieniać

    Obraz → Skaluj obraz: szerokość 100, wysokość 100 - kadr jest kwadratowy, więc proporcje się nie zmieniają. Zapis pod tą samą nazwą: Plik → Nadpisz osoba1.jpg (zwykłe Zapisz w GIMP-ie zapisuje format .xcf). Zdjęcia osoba2.jpg - osoba8.jpg mają już 100 × 100 px i zostają bez zmian.

    Typowe błędy

    Skalowanie całego zdjęcia 300 × 200 do 100 × 100 bez kadrowania spłaszczy twarz.

    Podgląd strony po tym kroku
    Podgląd strony po kroku 9
  10. Krok 10: Plik settings.html

    ok. 1 min
    Polecenie z arkusza

    Odsyłacz o treści „Inne ustawienia” prowadzący do strony settings.html (należy utworzyć plik settings.html i zapisać w nim treść: „strona w trakcie budowy”)

    Najpierw cel odsyłacza: w edytorze tworzysz plik settings.html z jednym zdaniem: strona w trakcie budowy. Arkusz każe zapisać w nim tylko tę treść, więc bez szkieletu HTML - przeglądarka i tak wyświetli tekst. Sam odsyłacz powstanie w bloku lewym.

    settings.html HTML nowy plik
    strona w trakcie budowy
    Podgląd strony po tym kroku (settings.html)
  11. Krok 11: Plik users.php

    Kryteria:

    R.2.2 Witrynę internetową zapisano w pliku PHP o nazwie users.php

    ok. 2 min
    Polecenie z arkusza

    Składa się ze strony o nazwie users.php

    Plik users.php w folderze zdającego, obok zdjęć. Rozszerzenie .php, bo dojdą skrypty - na razie to czysty HTML. <!DOCTYPE html> oznacza HTML5, lang="pl" mówi przeglądarce i czytnikom ekranu, że treść jest po polsku. Nazwę pliku sprawdza klucz (R.2.2).

    users.php PHP nowy plik
    <!DOCTYPE html>
    <html lang="pl">
    <head>
    </head>
    <body>
    </body>
    </html>
    Podgląd strony po tym kroku (users.php)
  12. Krok 12: Kodowanie polskich znaków

    Kryteria:

    R.2.3 Zastosowano właściwy standard kodowania polskich znaków dla witryny

    ok. 1 min
    Polecenie z arkusza

    Zastosowany właściwy standard kodowania polskich znaków

    <meta charset="UTF-8"> jako pierwsza rzecz w <head>. Bez tej linii „Społecznościowy” i „Użytkownicy” mogą wyświetlić się jako krzaki. Plik trzeba też zapisać w UTF-8.

    users.php PHP zmienione: 1 linia
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
    </head>
    <body>
    </body>
    </html>
    Podgląd strony po tym kroku (users.php)
  13. Krok 13: Tytuł strony

    Kryteria:

    R.2.4 Nadano tytuł strony: "Panel administratora”

    ok. 1 min
    Polecenie z arkusza

    Tytuł strony widoczny na karcie przeglądarki: „Panel administratora”

    <title> w <head> - napis na karcie przeglądarki, a nie na stronie.

    users.php PHP zmienione: 1 linia
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <title>Panel administratora</title>
    </head>
    <body>
    </body>
    </html>
    Podgląd strony po tym kroku (users.php)
  14. Krok 14: Podpięcie arkusza stylów styl4.css

    Kryteria:

    R.3.5 Strona zawiera działające połączenie z zewnętrznym arkuszem stylów o nazwie styl4.css , formatowanie pochodzi jedynie z tego arkusza Uwaga: kryterium to nie jest spełnione również, gdy źle przypisano co najmniej jednen selektor do bloku (np. kropka zamiast #)

    ok. 1 min
    Polecenie z arkusza

    Arkusz stylów w pliku o nazwie styl4.css prawidłowo połączony z kodem strony

    <link rel="stylesheet" href="styl4.css"> w <head>. Nazwa ma w sobie cyfrę: styl4.css, nie styl.css. Plik stylów powstanie po HTML-u.

    Typowe błędy

    Klucz uznaje R.3.5 tylko przy działającym połączeniu, w którym wszystkie selektory trafiają w bloki - kropka zamiast # przy identyfikatorze odbiera punkt.

    users.php PHP zmienione: 1 linia
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <title>Panel administratora</title>
        <link rel="stylesheet" href="styl4.css">
    </head>
    <body>
    </body>
    </html>
    Podgląd strony po tym kroku (users.php)
  15. Krok 15: Bloki: baner, lewy, prawy i stopka

    Kryteria:

    R.2.5 Wygląd strony zdefiniowano dzieląc ją na bloki: baner, lewy i prawy, stopka. Zastosowano znaczniki sekcji

    ok. 2 min
    Polecenie z arkusza

    Podział strony na bloki: baner, lewy i prawy, stopka. Podział zrealizowany za pomocą znaczników sekcji tak, aby wygląd układu bloków strony po uruchomieniu w przeglądarce, był zgodny z Obrazem 2

    Cztery bloki w kolejności z obrazu 2: baner <header>, blok lewy i prawy jako <section>, stopka <footer>. Obie sekcje mają te same style, ale różną treść, więc dostają identyfikatory: left i right (nazwy po angielsku - arkusz ich nie narzuca). Na razie bloki są puste i stoją jeden pod drugim; obok siebie ustawi je CSS.

    users.php PHP zmienione: 8 linii
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <title>Panel administratora</title>
        <link rel="stylesheet" href="styl4.css">
    </head>
    <body>
        <header>
        </header>
        <section id="left">
        </section>
        <section id="right">
        </section>
        <footer>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (users.php)
  16. Krok 16: Baner: nagłówek trzeciego stopnia

    ok. 1 min
    Polecenie z arkusza

    Zawartość banera: nagłówek trzeciego stopnia o treści „Portal Społecznościowy - panel administratora”

    W tym arkuszu baner ma nagłówek trzeciego stopnia - <h3>, a nie <h1>. Klucz R.2.6 sprawdza go razem z dwoma nagłówkami <h4> bloków.

    users.php PHP zmienione: 1 linia
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <title>Panel administratora</title>
        <link rel="stylesheet" href="styl4.css">
    </head>
    <body>
        <header>
            <h3>Portal Społecznościowy - panel administratora</h3>
        </header>
        <section id="left">
        </section>
        <section id="right">
        </section>
        <footer>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (users.php)
  17. Krok 17: Blok lewy: nagłówek „Użytkownicy”

    ok. 1 min
    Polecenie z arkusza

    Zawartość bloku lewego: Nagłówek czwartego stopnia o treści „Użytkownicy”

    Czwartego stopnia to <h4>. Pod nim stanie wynik skryptu 1 - lista użytkowników.

    users.php PHP zmienione: 1 linia
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <title>Panel administratora</title>
        <link rel="stylesheet" href="styl4.css">
    </head>
    <body>
        <header>
            <h3>Portal Społecznościowy - panel administratora</h3>
        </header>
        <section id="left">
            <h4>Użytkownicy</h4>
        </section>
        <section id="right">
        </section>
        <footer>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (users.php)
  18. Krok 18: Blok lewy: odsyłacz „Inne ustawienia”

    Kryteria:

    R.3.2 Na stronie umieszczono odnośnik "Inne ustawienia", po jego wybraniu otwiera się strona settings.html

    ok. 1 min
    Polecenie z arkusza

    Odsyłacz o treści „Inne ustawienia” prowadzący do strony settings.html

    <a href="settings.html"> - kliknięcie otwiera plik z poprzedniego kroku, z tego samego folderu (R.3.2). Odsyłacz jest ostatni w bloku lewym: skrypt 1 wpisze listę użytkowników między nagłówkiem a odsyłaczem, jak na obrazie 2.

    users.php PHP zmienione: 1 linia
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <title>Panel administratora</title>
        <link rel="stylesheet" href="styl4.css">
    </head>
    <body>
        <header>
            <h3>Portal Społecznościowy - panel administratora</h3>
        </header>
        <section id="left">
            <h4>Użytkownicy</h4>
            <a href="settings.html">Inne ustawienia</a>
        </section>
        <section id="right">
        </section>
        <footer>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (users.php)
  19. Krok 19: Blok prawy: nagłówek „Podaj id użytkownika”

    Kryteria:

    R.2.6 W bloku banera zapisano nagłówek h3: "Portal Społecznościowy - panel administratora" oraz w bloku lewym nagłówek h4: "Użytkownicy" i w bloku prawym nagłówek h4: "Podaj id użytkownika"

    ok. 1 min
    Polecenie z arkusza

    Zawartość bloku prawego: Nagłówek czwartego stopnia o treści „Podaj id użytkownika”

    Drugi <h4>. Strona ma już komplet nagłówków: <h3> w banerze i dwa <h4> w blokach (R.2.6).

    users.php PHP zmienione: 1 linia
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <title>Panel administratora</title>
        <link rel="stylesheet" href="styl4.css">
    </head>
    <body>
        <header>
            <h3>Portal Społecznościowy - panel administratora</h3>
        </header>
        <section id="left">
            <h4>Użytkownicy</h4>
            <a href="settings.html">Inne ustawienia</a>
        </section>
        <section id="right">
            <h4>Podaj id użytkownika</h4>
        </section>
        <footer>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (users.php)
  20. Krok 20: Formularz wysyłający dane metodą POST

    Kryteria:

    R.3.3 Formularz wysyła dane do tego samego pliku metodą POST

    ok. 1 min
    Polecenie z arkusza

    Formularz wysyłający dane metodą post do tego samego pliku i zawierający:

    <form method="post"> - bez atrybutu action formularz wysyła dane do tego samego adresu, z którego został wczytany, czyli do users.php (R.3.3). Metoda POST przesyła dane w treści żądania; w PHP odczytasz je z tablicy $_POST.

    Typowe błędy

    method="get" dopisze identyfikator do adresu (users.php?id=10), a skrypt czytający $_POST niczego nie dostanie.

    users.php PHP zmienione: 2 linie
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <title>Panel administratora</title>
        <link rel="stylesheet" href="styl4.css">
    </head>
    <body>
        <header>
            <h3>Portal Społecznościowy - panel administratora</h3>
        </header>
        <section id="left">
            <h4>Użytkownicy</h4>
            <a href="settings.html">Inne ustawienia</a>
        </section>
        <section id="right">
            <h4>Podaj id użytkownika</h4>
            <form method="post">
            </form>
        </section>
        <footer>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (users.php)
  21. Krok 21: Pole edycyjne typu numerycznego

    ok. 1 min
    Polecenie z arkusza

    pole edycyjne typu numerycznego

    <input type="number"> - przeglądarka pokaże strzałki do zmiany wartości i nie pozwoli wpisać liter. Atrybut name="id" to klucz, pod którym wartość trafi do PHP: $_POST['id'].

    Typowe błędy

    type="text" wygląda podobnie, ale klucz R.3.4 wymaga pola typu number.

    users.php PHP zmienione: 1 linia
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <title>Panel administratora</title>
        <link rel="stylesheet" href="styl4.css">
    </head>
    <body>
        <header>
            <h3>Portal Społecznościowy - panel administratora</h3>
        </header>
        <section id="left">
            <h4>Użytkownicy</h4>
            <a href="settings.html">Inne ustawienia</a>
        </section>
        <section id="right">
            <h4>Podaj id użytkownika</h4>
            <form method="post">
                <input type="number" name="id">
            </form>
        </section>
        <footer>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (users.php)
  22. Krok 22: Przycisk „ZOBACZ”

    Kryteria: ,

    R.2.7 W bloku prawym umieszczono formularz z polem edycyjnym i przyciskiem, zastosowano zancznik <form> oraz jego zamknięcie

    R.3.4 Pole edycyjne formularza jest typu number, przycisk ZOBACZ wysyła dane z formularza (np. typ submit dla input lub button albo button bez typu)

    ok. 1 min
    Polecenie z arkusza

    przycisk wysyłający dane o treści "ZOBACZ”

    <button type="submit">ZOBACZ</button> - przycisk wysyłający formularz, z napisem wielkimi literami jak w arkuszu. Formularz ma komplet: pole i przycisk w znaczniku <form> z zamknięciem (R.2.7), pole typu number i przycisk, który wysyła dane (R.3.4). Znacznik <button> da się w CSS złapać prostym selektorem button, a styl przycisku jest w tym arkuszu osobnym wymaganiem.

    Typowe błędy

    <button type="button"> niczego nie wysyła - brak punktu R.3.4 i skrypt 2 nigdy się nie uruchomi.

    users.php PHP zmienione: 1 linia
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <title>Panel administratora</title>
        <link rel="stylesheet" href="styl4.css">
    </head>
    <body>
        <header>
            <h3>Portal Społecznościowy - panel administratora</h3>
        </header>
        <section id="left">
            <h4>Użytkownicy</h4>
            <a href="settings.html">Inne ustawienia</a>
        </section>
        <section id="right">
            <h4>Podaj id użytkownika</h4>
            <form method="post">
                <input type="number" name="id">
                <button type="submit">ZOBACZ</button>
            </form>
        </section>
        <footer>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (users.php)
  23. Krok 23: Blok prawy: linia pozioma

    ok. 1 min
    Polecenie z arkusza

    Linia pozioma

    <hr> pod formularzem - oddziela formularz od karty osoby, którą wypisze skrypt 2. Znacznik nie ma zamknięcia.

    users.php PHP zmienione: 1 linia
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <title>Panel administratora</title>
        <link rel="stylesheet" href="styl4.css">
    </head>
    <body>
        <header>
            <h3>Portal Społecznościowy - panel administratora</h3>
        </header>
        <section id="left">
            <h4>Użytkownicy</h4>
            <a href="settings.html">Inne ustawienia</a>
        </section>
        <section id="right">
            <h4>Podaj id użytkownika</h4>
            <form method="post">
                <input type="number" name="id">
                <button type="submit">ZOBACZ</button>
            </form>
            <hr>
        </section>
        <footer>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (users.php)
  24. Krok 24: Stopka z autorem strony

    Kryteria:

    R.2.8 W stopce umieszczono napis „Stronę wykonał: ”, dalej wstawiony numer PESEL zdającego

    ok. 1 min
    Polecenie z arkusza

    Zawartość stopki: napis o treści „Stronę wykonał: ”, dalej wstawiony numer PESEL zdającego lub w przypadku jego braku inny numer, którym został podpisany arkusz

    Na egzaminie po dwukropku wpisujesz swój numer PESEL. W tym rozwiązaniu w jego miejscu stoi imię i nazwisko autora: Bartosz Bryniarski.

    users.php PHP zmienione: 1 linia
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <title>Panel administratora</title>
        <link rel="stylesheet" href="styl4.css">
    </head>
    <body>
        <header>
            <h3>Portal Społecznościowy - panel administratora</h3>
        </header>
        <section id="left">
            <h4>Użytkownicy</h4>
            <a href="settings.html">Inne ustawienia</a>
        </section>
        <section id="right">
            <h4>Podaj id użytkownika</h4>
            <form method="post">
                <input type="number" name="id">
                <button type="submit">ZOBACZ</button>
            </form>
            <hr>
        </section>
        <footer>
            Stronę wykonał: Bartosz Bryniarski
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (users.php)
  25. Etap 3: Styl CSS

    Kroki 25-30 · po tym etapie masz 27 z 35 kryteriów (pkt)

    Krok 25: Plik styl4.css: krój Helvetica dla całej strony

    Kryteria:

    R.4.1 Ustawiono domyślny krój czcionki dla całej strony na Helvetica (dla selektora * lub body lub html lub kontenera całej strony)

    ok. 1 min
    Polecenie z arkusza

    Cechy formatowania CSS: Domyślne dla całej strony: krój czcionki Helvetica

    Nowy plik styl4.css w folderze zdającego. Pierwsza reguła: selektor uniwersalny * z font-family: Helvetica (R.4.1). Selektor * obejmuje też pole formularza i przycisk, które kroju po body nie dziedziczą. Windows nie ma kroju Helvetica - przeglądarka podstawi wtedy Arial, który wygląda prawie tak samo.

    styl4.css CSS nowy plik
    * {
        font-family: Helvetica;
    }
    Podgląd strony po tym kroku (users.php)
  26. Krok 26: Baner i stopka: tło, kolor, wyśrodkowanie, wysokość

    Kryteria: ,

    R.4.3 Ustawiono biały kolor czcionki dla banera i stopki

    R.4.6 Ustawiono wyrównanie tekstu do środka dla banera i stopki

    ok. 2 min
    Polecenie z arkusza

    Dla banera i stopki: kolor tła #AF4448, biały kolor czcionki, wyrównanie tekstu do środka, wysokość 20 px

    Dwa selektory rozdzielone przecinkiem dostają jedną wspólną regułę. Biały tekst (R.4.3) i wyśrodkowanie (R.4.6) banera i stopki są ustawione.

    styl4.css CSS zmienione: 6 linii
    * {
        font-family: Helvetica;
    }
    header, footer {
        background-color: #AF4448;
        color: white;
        text-align: center;
        height: 20px;
    }
    Podgląd strony po tym kroku (users.php)
  27. Krok 27: Blok lewy i prawy: tło, wysokość, szerokość

    Kryteria: , ,

    R.4.2 Ustawiono kolor tła #AF4448 dla banera i stopki oraz #FFA4A2 dla bloku lewego i prawego

    R.4.4 Ustawiono wysokość bloków: baner i stopka 20px, lewy i prawy 650px

    R.4.5 Ustawiono szerokość bloków prawego i lewego 50%

    ok. 2 min
    Polecenie z arkusza

    Dla bloku lewego i prawego: kolor tła #FFA4A2, wysokość 650 px, szerokość 50%

    Selektory identyfikatorów #left i #right - z krzyżykiem, bo w HTML-u są atrybuty id. Kolory tła wszystkich bloków (R.4.2), wysokości (R.4.4) i szerokości (R.4.5) są ustawione.

    Typowe błędy

    Bloki o sumie szerokości 100% nie mogą mieć marginesów, padding ani obramowań - każdy piksel więcej zepchnie blok prawy pod lewy.

    styl4.css CSS zmienione: 5 linii
    * {
        font-family: Helvetica;
    }
    header, footer {
        background-color: #AF4448;
        color: white;
        text-align: center;
        height: 20px;
    }
    #left, #right {
        background-color: #FFA4A2;
        height: 650px;
        width: 50%;
    }
    Podgląd strony po tym kroku (users.php)
  28. Krok 28: Układ bloków zgodny z obrazem 2

    Kryteria:

    R.3.1 Układ bloków po uruchomieniu strony w przeglądarce jest zgodny z Obrazem 2 w arkuszu egzaminacyjnym

    ok. 2 min
    Polecenie z arkusza

    Podział zrealizowany za pomocą znaczników sekcji tak, aby wygląd układu bloków strony po uruchomieniu w przeglądarce, był zgodny z Obrazem 2

    Obie sekcje dostają float: left: blok lewy staje przy lewej krawędzi, prawy tuż obok niego - razem 50% + 50%. Stopka z clear: both zaczyna się dopiero pod pływającymi blokami (R.3.1). Arkusz nie podaje tych właściwości, ale wymaga układu z obrazu 2.

    Typowe błędy

    Bez clear: both stopka wsunie się pod pływające bloki i jej pasek schowa się za nimi.

    styl4.css CSS zmienione: 6 linii
    * {
        font-family: Helvetica;
    }
    header, footer {
        background-color: #AF4448;
        color: white;
        text-align: center;
        height: 20px;
    }
    #left, #right {
        background-color: #FFA4A2;
        height: 650px;
        width: 50%;
    }
    section {
        float: left;
    }
    footer {
        clear: both;
    }
    Podgląd strony po tym kroku (users.php)
  29. Krok 29: Nagłówki czwartego stopnia: marginesy zewnętrzne 0

    Kryteria:

    R.4.7 Ustawiono marginesy zewnętrzne (margin) dla selektora h4 na 0px (0 poprawnie też bez jednostki)

    ok. 1 min
    Polecenie z arkusza

    Dla selektora nagłówka czwartego stopnia: marginesy zewnętrzne 0 px

    Przeglądarka daje nagłówkom domyślne marginesy zewnętrzne. margin: 0 (przy zerze jednostka nie jest potrzebna) dosuwa „Użytkownicy” i „Podaj id użytkownika” do górnej krawędzi bloków, jak na obrazie 2 (R.4.7).

    styl4.css CSS zmienione: 3 linie
    * {
        font-family: Helvetica;
    }
    header, footer {
        background-color: #AF4448;
        color: white;
        text-align: center;
        height: 20px;
    }
    #left, #right {
        background-color: #FFA4A2;
        height: 650px;
        width: 50%;
    }
    section {
        float: left;
    }
    footer {
        clear: both;
    }
    h4 {
        margin: 0;
    }
    Podgląd strony po tym kroku (users.php)
  30. Krok 30: Przycisk: tło, kolor, marginesy wewnętrzne i zewnętrzne

    Kryteria:

    R.4.8 Ustawiono styl przycisku wysyłającego dane z formularza: kolor tła #AF4448, biały kolor czcionki, marginesy wewnętrzne (padding) 5px oraz zewnętrzne (margin) 10px

    ok. 2 min
    Polecenie z arkusza

    Dla przycisku wysyłającego dane z formularza: kolor tła #AF4448, biały kolor czcionki, marginesy wewnętrzne 5 px, marginesy zewnętrzne 10 px

    Selektor znacznika button - na stronie jest jeden przycisk. padding (margines wewnętrzny) powiększa przycisk wokół napisu, margin (zewnętrzny) odsuwa go od pola i krawędzi bloku (R.4.8). Arkusz stylów jest kompletny.

    Typowe błędy

    Gdyby przycisk był zapisany jako <input type="submit">, selektor musiałby brzmieć input[type="submit"] - sam input objąłby też pole liczby.

    styl4.css CSS zmienione: 6 linii
    * {
        font-family: Helvetica;
    }
    header, footer {
        background-color: #AF4448;
        color: white;
        text-align: center;
        height: 20px;
    }
    #left, #right {
        background-color: #FFA4A2;
        height: 650px;
        width: 50%;
    }
    section {
        float: left;
    }
    footer {
        clear: both;
    }
    h4 {
        margin: 0;
    }
    button {
        background-color: #AF4448;
        color: white;
        padding: 5px;
        margin: 10px;
    }
    Podgląd strony po tym kroku (users.php)
  31. Etap 4: Skrypt PHP

    Kroki 31-39 · po tym etapie masz 35 z 35 kryteriów (pkt)

    Krok 31: Skrypt 1: miejsce i połączenie z bazą dane4

    Kryteria:

    R.5.1 Skrypt realizuje połączenie z serwerem bazy danych i wybór bazy dane4

    ok. 3 min
    Polecenie z arkusza

    Skrypt łączy się z serwerem bazy danych na localhost, użytkownik root bez hasła, baza danych o nazwie dane4

    „Efekt działania skryptu 1” ma być w bloku lewym, między nagłówkiem a odsyłaczem (obraz 2) - tam piszesz pierwszy blok PHP, między <?php a ?>. Serwer wykona go, zanim strona trafi do przeglądarki.

    Pierwsza instrukcja: mysqli_connect z tabeli 1 arkusza - kolejno serwer localhost, użytkownik root, puste hasło '' i nazwa bazy dane4. Połączenie trafia do zmiennej $connection i wystarczy dla obu skryptów: zmienne z jednego bloku PHP są widoczne w kolejnych blokach tego samego pliku (R.5.1).

    Od tego kroku podgląd to wynik działania strony po stronie serwera (prawdziwe uruchomienie w PHP 8.2) - na razie wygląda jak wcześniej. Stronę sprawdzasz przez http://localhost/…, a nie otwierając plik z dysku: przeglądarka sama nie wykona PHP.

    users.php PHP zmienione: 3 linie
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <title>Panel administratora</title>
        <link rel="stylesheet" href="styl4.css">
    </head>
    <body>
        <header>
            <h3>Portal Społecznościowy - panel administratora</h3>
        </header>
        <section id="left">
            <h4>Użytkownicy</h4>
    <?php
    $connection = mysqli_connect('localhost', 'root', '', 'dane4');
    ?>
            <a href="settings.html">Inne ustawienia</a>
        </section>
        <section id="right">
            <h4>Podaj id użytkownika</h4>
            <form method="post">
                <input type="number" name="id">
                <button type="submit">ZOBACZ</button>
            </form>
            <hr>
        </section>
        <footer>
            Stronę wykonał: Bartosz Bryniarski
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (users.php)
  32. Krok 32: Skrypt 1: zapytanie 1 wysłane do bazy

    Kryteria:

    R.5.3 Skrypt 1 wysyła do bazy danych zapytanie 1 lub skrypt 2 wysyła zapytanie 2 zmodyfikowane w ten sposób, że w warunku jest przypisane id podane w formularzu

    ok. 2 min
    Polecenie z arkusza

    Działanie skryptu 1 w panelu lewym: Wysyła do bazy danych zapytanie 1

    mysqli_query($connection, '…') wysyła zapytanie 1 skopiowane z kwerendy.txt (R.5.3). Wynik - 30 wierszy - trafia do zmiennej $result; strona jeszcze niczego nie wypisuje.

    users.php PHP zmienione: 1 linia
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <title>Panel administratora</title>
        <link rel="stylesheet" href="styl4.css">
    </head>
    <body>
        <header>
            <h3>Portal Społecznościowy - panel administratora</h3>
        </header>
        <section id="left">
            <h4>Użytkownicy</h4>
    <?php
    $connection = mysqli_connect('localhost', 'root', '', 'dane4');
    $result = mysqli_query($connection, 'SELECT id, imie, nazwisko, rok_urodzenia, zdjecie FROM osoby LIMIT 30;');
    ?>
            <a href="settings.html">Inne ustawienia</a>
        </section>
        <section id="right">
            <h4>Podaj id użytkownika</h4>
            <form method="post">
                <input type="number" name="id">
                <button type="submit">ZOBACZ</button>
            </form>
            <hr>
        </section>
        <footer>
            Stronę wykonał: Bartosz Bryniarski
        </footer>
    </body>
    </html>

    Podgląd strony bez zmian - taki jak po kroku 31.

  33. Krok 33: Skrypt 1: każdy użytkownik w osobnej linii

    Kryteria:

    R.5.5 Skrypt 1 Wyświetla każdy zwrócony zapytaniem wiersz w osobnej linii o treści: "<id>. <imie> <nazwisko>" gdzie pola <id>, <imie>, <nazwisko> zostały pobrane z bazy (wiek nie jest sprawdzany w tym kryterium)

    ok. 3 min
    Polecenie z arkusza

    Dla każdego wiersza zwróconego zapytaniem: Wyświetla w osobnej linii treść: <id>. <imie> <nazwisko>, < wiek> lat, gdzie pola <id>, <imie>, <nazwisko> zostały pobrane z bazy, a <wiek> oznacza obliczony wiek osoby

    • while ($row = mysqli_fetch_row($result)) - funkcja z tabeli 1 zwraca kolejny wiersz jako tablicę numerowaną od zera, w kolejności kolumn z zapytania: $row[0] id, $row[1] imię, $row[2] nazwisko, $row[3] rok urodzenia, $row[4] zdjęcie. Gdy wierszy zabraknie, zwraca false i pętla się kończy,
    • echo skleja (operatorem .) identyfikator, kropkę ze spacją, imię, spację i nazwisko, a <br> na końcu przenosi kolejną osobę do nowej linii (R.5.5).

    Podgląd: 30 linii, od „2. Monika Kowalska” do „31. Grzegorz Roh”. Wiek dojdzie w następnym kroku - klucz ocenia go osobno.

    Typowe błędy

    Bez <br> wszystkie osoby sklejają się w jeden długi wiersz tekstu - przeglądarka ignoruje znaki nowej linii w HTML-u.

    users.php PHP zmienione: 3 linie
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <title>Panel administratora</title>
        <link rel="stylesheet" href="styl4.css">
    </head>
    <body>
        <header>
            <h3>Portal Społecznościowy - panel administratora</h3>
        </header>
        <section id="left">
            <h4>Użytkownicy</h4>
    <?php
    $connection = mysqli_connect('localhost', 'root', '', 'dane4');
    $result = mysqli_query($connection, 'SELECT id, imie, nazwisko, rok_urodzenia, zdjecie FROM osoby LIMIT 30;');
    while ($row = mysqli_fetch_row($result)) {
        echo $row[0] . '. ' . $row[1] . ' ' . $row[2] . '<br>';
    }
    ?>
            <a href="settings.html">Inne ustawienia</a>
        </section>
        <section id="right">
            <h4>Podaj id użytkownika</h4>
            <form method="post">
                <input type="number" name="id">
                <button type="submit">ZOBACZ</button>
            </form>
            <hr>
        </section>
        <footer>
            Stronę wykonał: Bartosz Bryniarski
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (users.php)
  34. Krok 34: Skrypt 1: wiek obliczony z roku urodzenia

    Kryteria:

    R.5.4 Skrypt 1 oblicza wiek osoby na podstawie jej roku urodzenia, np. z wykorzystaniem funkcji date('Y') lub wykorzystując rok 2019 lub 2021

    ok. 2 min
    Polecenie z arkusza

    Oblicza wiek osoby na podstawie jej roku urodzenia

    date('Y') zwraca bieżący rok czterema cyframi; odjęcie roku urodzenia daje wiek (z dokładnością do roku - arkusz nie podaje dnia urodzenia). Wynik trafia do zmiennej $age i do linii: „, ” + wiek + „ lat” (R.5.4).

    Podgląd liczy od roku 2026: Monika Kowalska z rocznika 1976 ma 50 lat. Na obrazie 2 w arkuszu stoi „43 lat”, bo zrzut zrobiono w 2019 roku - klucz przyjmuje date('Y'), a także rok 2019 albo 2021 wpisany na stałe.

    Typowe błędy

    Rok wpisany na stałe (2021 - $row[3]) za rok pokaże zły wiek. date('y') z małą literą zwraca dwie cyfry (np. 21) i daje ujemny wiek.

    users.php PHP zmienione: 2 linie
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <title>Panel administratora</title>
        <link rel="stylesheet" href="styl4.css">
    </head>
    <body>
        <header>
            <h3>Portal Społecznościowy - panel administratora</h3>
        </header>
        <section id="left">
            <h4>Użytkownicy</h4>
    <?php
    $connection = mysqli_connect('localhost', 'root', '', 'dane4');
    $result = mysqli_query($connection, 'SELECT id, imie, nazwisko, rok_urodzenia, zdjecie FROM osoby LIMIT 30;');
    while ($row = mysqli_fetch_row($result)) {
        $age = date('Y') - $row[3];
        echo $row[0] . '. ' . $row[1] . ' ' . $row[2] . ', ' . $age . ' lat<br>';
    }
    ?>
            <a href="settings.html">Inne ustawienia</a>
        </section>
        <section id="right">
            <h4>Podaj id użytkownika</h4>
            <form method="post">
                <input type="number" name="id">
                <button type="submit">ZOBACZ</button>
            </form>
            <hr>
        </section>
        <footer>
            Stronę wykonał: Bartosz Bryniarski
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (users.php)
  35. Krok 35: Skrypt 2: identyfikator z formularza w zapytaniu 2

    ok. 4 min
    Polecenie z arkusza

    Działanie skryptu 2 w panelu prawym wykonywanego po wypełnieniu formularza: Wysyła do bazy danych zapytanie 2, zmodyfikowane w ten sposób, że w warunku zamiast przypisanego numeru id równego 10, jest numer id przesłany z formularza

    Drugi blok PHP stoi w bloku prawym, pod linią poziomą:

    • isset($_POST['id']) - prawdziwe dopiero po kliknięciu „ZOBACZ”. Przy pierwszym wejściu formularz nie był wysłany i skrypt 2 nic nie robi,
    • $id = $_POST['id']; - wartość pola o nazwie id,
    • zapytanie 2 z kwerendy.txt z jedną zmianą: w miejscu 10 stoi $id. Całe zapytanie jest w cudzysłowie "…", więc PHP podstawia wartość zmiennej (w apostrofach by tego nie zrobił),
    • mysqli_fetch_row odczytuje jedyny wiersz wyniku do $row: $row[0] imię, $row[1] nazwisko, $row[2] rok urodzenia, $row[3] opis, $row[4] zdjęcie, $row[5] nazwa hobby.

    Klucz przyjmuje R.5.3 za skrypt 1 albo skrypt 2 - punkt jest już przyznany. Podgląd: formularz wysłany z wartością 10, jak na obrazie 2; karta osoby pojawi się w kolejnych krokach.

    users.php PHP zmienione: 7 linii
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <title>Panel administratora</title>
        <link rel="stylesheet" href="styl4.css">
    </head>
    <body>
        <header>
            <h3>Portal Społecznościowy - panel administratora</h3>
        </header>
        <section id="left">
            <h4>Użytkownicy</h4>
    <?php
    $connection = mysqli_connect('localhost', 'root', '', 'dane4');
    $result = mysqli_query($connection, 'SELECT id, imie, nazwisko, rok_urodzenia, zdjecie FROM osoby LIMIT 30;');
    while ($row = mysqli_fetch_row($result)) {
        $age = date('Y') - $row[3];
        echo $row[0] . '. ' . $row[1] . ' ' . $row[2] . ', ' . $age . ' lat<br>';
    }
    ?>
            <a href="settings.html">Inne ustawienia</a>
        </section>
        <section id="right">
            <h4>Podaj id użytkownika</h4>
            <form method="post">
                <input type="number" name="id">
                <button type="submit">ZOBACZ</button>
            </form>
            <hr>
    <?php
    if (isset($_POST['id'])) {
        $id = $_POST['id'];
        $result = mysqli_query($connection, "SELECT imie, nazwisko, rok_urodzenia, opis, zdjecie, nazwa FROM osoby JOIN hobby ON osoby.Hobby_id = hobby.id WHERE osoby.id = $id;");
        $row = mysqli_fetch_row($result);
    }
    ?>
        </section>
        <footer>
            Stronę wykonał: Bartosz Bryniarski
        </footer>
    </body>
    </html>

    Podgląd strony bez zmian - taki jak po kroku 34.

  36. Krok 36: Skrypt 2: nagłówek z identyfikatorem, imieniem i nazwiskiem

    Kryteria:

    R.5.6 Skrypt 2 wyświetla nagłówek h2 o treści <id>. <imie> <nazwisko>, gdzie pole <id> jest identyfikatorem pobranym z formularza, a pola <imie>, <nazwisko> są polami pobranymi z bazy

    ok. 2 min
    Polecenie z arkusza

    Wyświetla nagłówek drugiego stopnia o treści <id>. <imie> <nazwisko>, gdzie pole <id> jest identyfikatorem pobranym z formularza, a pola <imie>, <nazwisko> są polami pobranymi z bazy

    <h2> z identyfikatorem z formularza ($id), kropką i imieniem oraz nazwiskiem z bazy. Podgląd: „10. Roksana Rybnik” (R.5.6).

    users.php PHP zmienione: 1 linia
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <title>Panel administratora</title>
        <link rel="stylesheet" href="styl4.css">
    </head>
    <body>
        <header>
            <h3>Portal Społecznościowy - panel administratora</h3>
        </header>
        <section id="left">
            <h4>Użytkownicy</h4>
    <?php
    $connection = mysqli_connect('localhost', 'root', '', 'dane4');
    $result = mysqli_query($connection, 'SELECT id, imie, nazwisko, rok_urodzenia, zdjecie FROM osoby LIMIT 30;');
    while ($row = mysqli_fetch_row($result)) {
        $age = date('Y') - $row[3];
        echo $row[0] . '. ' . $row[1] . ' ' . $row[2] . ', ' . $age . ' lat<br>';
    }
    ?>
            <a href="settings.html">Inne ustawienia</a>
        </section>
        <section id="right">
            <h4>Podaj id użytkownika</h4>
            <form method="post">
                <input type="number" name="id">
                <button type="submit">ZOBACZ</button>
            </form>
            <hr>
    <?php
    if (isset($_POST['id'])) {
        $id = $_POST['id'];
        $result = mysqli_query($connection, "SELECT imie, nazwisko, rok_urodzenia, opis, zdjecie, nazwa FROM osoby JOIN hobby ON osoby.Hobby_id = hobby.id WHERE osoby.id = $id;");
        $row = mysqli_fetch_row($result);
        echo '<h2>' . $id . '. ' . $row[0] . ' ' . $row[1] . '</h2>';
    }
    ?>
        </section>
        <footer>
            Stronę wykonał: Bartosz Bryniarski
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (users.php)
  37. Krok 37: Skrypt 2: zdjęcie z bazy, tekst alternatywny z formularza

    Kryteria:

    R.5.7 Skrypt 2 wyświetla zdjęcie tak, że źródłem jest plik o nazwie pobranej z bazy a tekstem alternatywnym jest identyfikator pobrany z formularza

    ok. 2 min
    Polecenie z arkusza

    Wyświetla zdjęcie tak, że źródłem jest plik o nazwie pobranej z bazy a tekstem alternatywnym jest identyfikator pobrany z formularza

    <img> z nazwą pliku z bazy w src ($row[4], dla id 10 to osoba3.jpg) i identyfikatorem z formularza w alt - tak każe arkusz, choć zwykle tekst alternatywny opisuje zdjęcie (R.5.7).

    users.php PHP zmienione: 1 linia
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <title>Panel administratora</title>
        <link rel="stylesheet" href="styl4.css">
    </head>
    <body>
        <header>
            <h3>Portal Społecznościowy - panel administratora</h3>
        </header>
        <section id="left">
            <h4>Użytkownicy</h4>
    <?php
    $connection = mysqli_connect('localhost', 'root', '', 'dane4');
    $result = mysqli_query($connection, 'SELECT id, imie, nazwisko, rok_urodzenia, zdjecie FROM osoby LIMIT 30;');
    while ($row = mysqli_fetch_row($result)) {
        $age = date('Y') - $row[3];
        echo $row[0] . '. ' . $row[1] . ' ' . $row[2] . ', ' . $age . ' lat<br>';
    }
    ?>
            <a href="settings.html">Inne ustawienia</a>
        </section>
        <section id="right">
            <h4>Podaj id użytkownika</h4>
            <form method="post">
                <input type="number" name="id">
                <button type="submit">ZOBACZ</button>
            </form>
            <hr>
    <?php
    if (isset($_POST['id'])) {
        $id = $_POST['id'];
        $result = mysqli_query($connection, "SELECT imie, nazwisko, rok_urodzenia, opis, zdjecie, nazwa FROM osoby JOIN hobby ON osoby.Hobby_id = hobby.id WHERE osoby.id = $id;");
        $row = mysqli_fetch_row($result);
        echo '<h2>' . $id . '. ' . $row[0] . ' ' . $row[1] . '</h2>';
        echo '<img src="' . $row[4] . '" alt="' . $id . '">';
    }
    ?>
        </section>
        <footer>
            Stronę wykonał: Bartosz Bryniarski
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (users.php)
  38. Krok 38: Skrypt 2: trzy paragrafy - rok urodzenia, opis, hobby

    Kryteria:

    R.5.8 Skrypt 2 wyświetla trzy paragrafy (akapity) z rokiem urodzenia, opisem i hobby, wartości zostały pobrane z bazy

    ok. 2 min
    Polecenie z arkusza

    Wyświetla trzy paragrafy (akapity) o treści, kolejno: Rok urodzenia: <rok_urodzenia>, gdzie pole <rok_urodzenia> jest pobrane zapytaniem; Opis: <opis>, gdzie pole <opis> jest pobrane zapytaniem; Hobby: <nazwa>, gdzie pole <nazwa> jest pobrane zapytaniem

    Trzy echo, każdy z osobnym <p>, w kolejności z arkusza. Nazwa hobby pochodzi z tabeli hobby - dzięki złączeniu w zapytaniu 2 jest w tym samym wierszu co dane osoby. Podgląd: Rok urodzenia: 1995, Opis: pozdrawiam, Hobby: biegi - jak na obrazie 2 (R.5.8).

    users.php PHP zmienione: 3 linie
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <title>Panel administratora</title>
        <link rel="stylesheet" href="styl4.css">
    </head>
    <body>
        <header>
            <h3>Portal Społecznościowy - panel administratora</h3>
        </header>
        <section id="left">
            <h4>Użytkownicy</h4>
    <?php
    $connection = mysqli_connect('localhost', 'root', '', 'dane4');
    $result = mysqli_query($connection, 'SELECT id, imie, nazwisko, rok_urodzenia, zdjecie FROM osoby LIMIT 30;');
    while ($row = mysqli_fetch_row($result)) {
        $age = date('Y') - $row[3];
        echo $row[0] . '. ' . $row[1] . ' ' . $row[2] . ', ' . $age . ' lat<br>';
    }
    ?>
            <a href="settings.html">Inne ustawienia</a>
        </section>
        <section id="right">
            <h4>Podaj id użytkownika</h4>
            <form method="post">
                <input type="number" name="id">
                <button type="submit">ZOBACZ</button>
            </form>
            <hr>
    <?php
    if (isset($_POST['id'])) {
        $id = $_POST['id'];
        $result = mysqli_query($connection, "SELECT imie, nazwisko, rok_urodzenia, opis, zdjecie, nazwa FROM osoby JOIN hobby ON osoby.Hobby_id = hobby.id WHERE osoby.id = $id;");
        $row = mysqli_fetch_row($result);
        echo '<h2>' . $id . '. ' . $row[0] . ' ' . $row[1] . '</h2>';
        echo '<img src="' . $row[4] . '" alt="' . $id . '">';
        echo '<p>Rok urodzenia: ' . $row[2] . '</p>';
        echo '<p>Opis: ' . $row[3] . '</p>';
        echo '<p>Hobby: ' . $row[5] . '</p>';
    }
    ?>
        </section>
        <footer>
            Stronę wykonał: Bartosz Bryniarski
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (users.php)
  39. Krok 39: Zamknięcie połączenia z bazą

    Kryteria:

    R.5.2 Ostatnią operacją na bazie jest jej zamknięcie (zgodne ze składnią)

    ok. 1 min
    Polecenie z arkusza

    Po wykonaniu operacji na bazie danych skrypt zamyka połączenie z serwerem.

    mysqli_close($connection) na końcu drugiego bloku PHP, poza warunkiem if - wykona się zawsze, także wtedy, gdy formularz nie był wysłany. To ostatnia operacja na bazie (R.5.2): skrypt 1 skończył pracę wcześniej, więc połączenie można zamknąć dopiero tutaj. Strona spełnia wszystkie kryteria arkusza. Dalej dwa kroki o zabezpieczeniach - klucz ich nie wymaga.

    Typowe błędy

    mysqli_close na końcu skryptu 1 zamyka połączenie, zanim skrypt 2 wyśle zapytanie - po kliknięciu „ZOBACZ” PHP 8 kończy się błędem.

    users.php PHP zmienione: 1 linia
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <title>Panel administratora</title>
        <link rel="stylesheet" href="styl4.css">
    </head>
    <body>
        <header>
            <h3>Portal Społecznościowy - panel administratora</h3>
        </header>
        <section id="left">
            <h4>Użytkownicy</h4>
    <?php
    $connection = mysqli_connect('localhost', 'root', '', 'dane4');
    $result = mysqli_query($connection, 'SELECT id, imie, nazwisko, rok_urodzenia, zdjecie FROM osoby LIMIT 30;');
    while ($row = mysqli_fetch_row($result)) {
        $age = date('Y') - $row[3];
        echo $row[0] . '. ' . $row[1] . ' ' . $row[2] . ', ' . $age . ' lat<br>';
    }
    ?>
            <a href="settings.html">Inne ustawienia</a>
        </section>
        <section id="right">
            <h4>Podaj id użytkownika</h4>
            <form method="post">
                <input type="number" name="id">
                <button type="submit">ZOBACZ</button>
            </form>
            <hr>
    <?php
    if (isset($_POST['id'])) {
        $id = $_POST['id'];
        $result = mysqli_query($connection, "SELECT imie, nazwisko, rok_urodzenia, opis, zdjecie, nazwa FROM osoby JOIN hobby ON osoby.Hobby_id = hobby.id WHERE osoby.id = $id;");
        $row = mysqli_fetch_row($result);
        echo '<h2>' . $id . '. ' . $row[0] . ' ' . $row[1] . '</h2>';
        echo '<img src="' . $row[4] . '" alt="' . $id . '">';
        echo '<p>Rok urodzenia: ' . $row[2] . '</p>';
        echo '<p>Opis: ' . $row[3] . '</p>';
        echo '<p>Hobby: ' . $row[5] . '</p>';
    }
    mysqli_close($connection);
    ?>
        </section>
        <footer>
            Stronę wykonał: Bartosz Bryniarski
        </footer>
    </body>
    </html>

    Podgląd strony bez zmian - taki jak po kroku 38.

  40. Etap 5: Dobre praktyki (poza kluczem)

    Kroki 40-41 · po tym etapie masz 35 z 35 kryteriów (pkt)

    Krok 40: Zabezpieczenie: identyfikator jako liczba i zapytanie przygotowane

    ok. 4 min
    Polecenie z arkusza

    Wysyła do bazy danych zapytanie 2, zmodyfikowane w ten sposób, że w warunku zamiast przypisanego numeru id równego 10, jest numer id przesłany z formularza

    Pole type="number" pilnuje cyfr tylko w przeglądarce - żądanie POST można wysłać z pominięciem formularza, z dowolną treścią. Skrypt wkleja ją do zapytania wprost, a to SQL injection. Sprawdzone na wersji z poprzednich kroków:

    • id o treści 0 OR osoby.id = 2 zamienia warunek w WHERE osoby.id = 0 OR osoby.id = 2 i strona pokazuje inną osobę niż ta, o którą „pytano” - tak samo da się wyciągnąć dane z dowolnej tabeli bazy,
    • puste pole (kliknięcie „ZOBACZ” bez wpisania liczby) daje zapytanie WHERE osoby.id = ; - PHP 8.1 i nowsze zgłaszają wyjątek mysqli_sql_exception i zamiast strony widać „Fatal error”.

    Lekarstwo w dwóch warstwach. filter_var(…, FILTER_VALIDATE_INT) zwraca liczbę całkowitą albo false - wszystko inne dostaje komunikat zamiast zapytania. Do bazy idzie zapytanie przygotowane: mysqli_prepare ze znakiem ? w miejscu identyfikatora, mysqli_stmt_bind_param z typem 'i' (liczba całkowita), mysqli_stmt_execute i mysqli_stmt_get_result, który oddaje wynik do tej samej funkcji mysqli_fetch_row. Podgląd: ten sam „identyfikator-atak” kończy się komunikatem. Stare linie zostają w komentarzu.

    Typowe błędy

    Liczba liter w 'i' musi równać się liczbie znaków ? i liczbie zmiennych - inaczej mysqli_stmt_bind_param zgłosi błąd.

    users.php PHP zmienione: 17 linii
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <title>Panel administratora</title>
        <link rel="stylesheet" href="styl4.css">
    </head>
    <body>
        <header>
            <h3>Portal Społecznościowy - panel administratora</h3>
        </header>
        <section id="left">
            <h4>Użytkownicy</h4>
    <?php
    $connection = mysqli_connect('localhost', 'root', '', 'dane4');
    $result = mysqli_query($connection, 'SELECT id, imie, nazwisko, rok_urodzenia, zdjecie FROM osoby LIMIT 30;');
    while ($row = mysqli_fetch_row($result)) {
        $age = date('Y') - $row[3];
        echo $row[0] . '. ' . $row[1] . ' ' . $row[2] . ', ' . $age . ' lat<br>';
    }
    ?>
            <a href="settings.html">Inne ustawienia</a>
        </section>
        <section id="right">
            <h4>Podaj id użytkownika</h4>
            <form method="post">
                <input type="number" name="id">
                <button type="submit">ZOBACZ</button>
            </form>
            <hr>
    <?php
    if (isset($_POST['id'])) {
        // $id = $_POST['id'];
        // $result = mysqli_query($connection, "SELECT imie, nazwisko, rok_urodzenia, opis, zdjecie, nazwa FROM osoby JOIN hobby ON osoby.Hobby_id = hobby.id WHERE osoby.id = $id;");
        $id = filter_var($_POST['id'], FILTER_VALIDATE_INT);
        if ($id === false) {
            echo '<p>Podaj identyfikator - liczbę całkowitą.</p>';
        } else {
            $statement = mysqli_prepare($connection, 'SELECT imie, nazwisko, rok_urodzenia, opis, zdjecie, nazwa FROM osoby JOIN hobby ON osoby.Hobby_id = hobby.id WHERE osoby.id = ?');
            mysqli_stmt_bind_param($statement, 'i', $id);
            mysqli_stmt_execute($statement);
            $result = mysqli_stmt_get_result($statement);
            $row = mysqli_fetch_row($result);
            echo '<h2>' . $id . '. ' . $row[0] . ' ' . $row[1] . '</h2>';
            echo '<img src="' . $row[4] . '" alt="' . $id . '">';
            echo '<p>Rok urodzenia: ' . $row[2] . '</p>';
            echo '<p>Opis: ' . $row[3] . '</p>';
            echo '<p>Hobby: ' . $row[5] . '</p>';
        }
    }
    mysqli_close($connection);
    ?>
        </section>
        <footer>
            Stronę wykonał: Bartosz Bryniarski
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (users.php)
  41. Krok 41: Zabezpieczenie: brak osoby i htmlspecialchars na wyjściu

    ok. 4 min
    Polecenie z arkusza

    Wyświetla trzy paragrafy (akapity) o treści, kolejno: Rok urodzenia: <rok_urodzenia>, gdzie pole <rok_urodzenia> jest pobrane zapytaniem; Opis: <opis>, gdzie pole <opis> jest pobrane zapytaniem; Hobby: <nazwa>, gdzie pole <nazwa> jest pobrane zapytaniem

    Dwie poprawki tego, co strona wypisuje:

    • identyfikator, którego nie ma w bazie (np. 99), daje pusty wynik - mysqli_fetch_row zwraca null, a odczyt $row[0] z null w PHP 8 kończy się ostrzeżeniami „Trying to access array offset on value of type null” na stronie. Teraz jest na to komunikat,
    • htmlspecialchars dla każdej wartości z bazy (array_map przepuszcza przez funkcję cały wiersz naraz). Opis jest wpisem użytkownika portalu - sprawdzone: opis Roksany zmieniony na <b>Hej!</b> <script>…</script> bez tej funkcji wyświetla się pogrubiony, a skrypt z wpisu się wykonuje (atak XSS). Podgląd pokazuje ten sam wpis dosłownie, ze znacznikami.

    Identyfikator nie potrzebuje htmlspecialchars: po filter_var jest liczbą całkowitą. Na egzaminie wystarczy wersja sprzed etapu „Dobre praktyki” - klucz tych zabezpieczeń nie sprawdza.

    Typowe błędy

    htmlspecialchars przy zapisie do bazy zamiast przy wypisywaniu psuje dane (w bazie lądują encje). Dane w bazie zostają surowe, kodowanie robi się na wyjściu.

    users.php PHP zmienione: 10 linii
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <title>Panel administratora</title>
        <link rel="stylesheet" href="styl4.css">
    </head>
    <body>
        <header>
            <h3>Portal Społecznościowy - panel administratora</h3>
        </header>
        <section id="left">
            <h4>Użytkownicy</h4>
    <?php
    $connection = mysqli_connect('localhost', 'root', '', 'dane4');
    $result = mysqli_query($connection, 'SELECT id, imie, nazwisko, rok_urodzenia, zdjecie FROM osoby LIMIT 30;');
    while ($row = mysqli_fetch_row($result)) {
        $age = date('Y') - $row[3];
        echo $row[0] . '. ' . $row[1] . ' ' . $row[2] . ', ' . $age . ' lat<br>';
    }
    ?>
            <a href="settings.html">Inne ustawienia</a>
        </section>
        <section id="right">
            <h4>Podaj id użytkownika</h4>
            <form method="post">
                <input type="number" name="id">
                <button type="submit">ZOBACZ</button>
            </form>
            <hr>
    <?php
    if (isset($_POST['id'])) {
        // $id = $_POST['id'];
        // $result = mysqli_query($connection, "SELECT imie, nazwisko, rok_urodzenia, opis, zdjecie, nazwa FROM osoby JOIN hobby ON osoby.Hobby_id = hobby.id WHERE osoby.id = $id;");
        $id = filter_var($_POST['id'], FILTER_VALIDATE_INT);
        if ($id === false) {
            echo '<p>Podaj identyfikator - liczbę całkowitą.</p>';
        } else {
            $statement = mysqli_prepare($connection, 'SELECT imie, nazwisko, rok_urodzenia, opis, zdjecie, nazwa FROM osoby JOIN hobby ON osoby.Hobby_id = hobby.id WHERE osoby.id = ?');
            mysqli_stmt_bind_param($statement, 'i', $id);
            mysqli_stmt_execute($statement);
            $result = mysqli_stmt_get_result($statement);
            $row = mysqli_fetch_row($result);
            if ($row === null) {
                echo '<p>Nie ma użytkownika o identyfikatorze ' . $id . '.</p>';
            } else {
                $row = array_map('htmlspecialchars', $row);
                echo '<h2>' . $id . '. ' . $row[0] . ' ' . $row[1] . '</h2>';
                echo '<img src="' . $row[4] . '" alt="' . $id . '">';
                echo '<p>Rok urodzenia: ' . $row[2] . '</p>';
                echo '<p>Opis: ' . $row[3] . '</p>';
                echo '<p>Hobby: ' . $row[5] . '</p>';
            }
        }
    }
    mysqli_close($connection);
    ?>
        </section>
        <footer>
            Stronę wykonał: Bartosz Bryniarski
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (users.php)
  42. Etap 6: Oddanie pracy

    Krok 42 · po tym etapie masz 35 z 35 kryteriów (pkt)

    Krok 42: Plik przeglądarka.txt i nagranie płyty

    ok. 5 min
    Polecenie z arkusza

    UWAGA: po zakończeniu pracy utwórz w folderze z numerem PESEL lub w przypadku jego braku w folderze z innym numerem, którym został podpisany arkusz plik tekstowy o nazwie przeglądarka.txt. Zapisz w nim nazwę przeglądarki internetowej, w której weryfikowałeś poprawność działania witryny. Nagraj płytę z rezultatami pracy.

    W przeglądarka.txt wpisujesz nazwę przeglądarki, w której sprawdzasz stronę przez http://localhost/….

    W folderze z numerem zdającego muszą być: egzamin.jpg, kw1.png, kw2.png, kw3.png, kw4.png, kwerendy.txt, osoba1.jpg - osoba8.jpg, przeglądarka.txt, settings.html, styl4.css i users.php (plik dane.sql z archiwum może zostać). Nagraj płytę, sprawdź jej odczyt, opisz ją numerem zdającego i zostaw na stanowisku w pudełku razem z arkuszem. Pusta lub nieczytelna płyta to zero punktów za wszystkie pięć rezultatów.

    przeglądarka.txt Tekst nowy plik
    Google Chrome

    Podgląd strony bez zmian - taki jak po kroku 41.

Podgląd

To jedno z możliwych rozwiązań. Egzaminator ocenia spełnienie kryteriów z klucza odpowiedzi, a nie zgodność z tym kodem - inna, poprawna droga też daje punkty.

Autor rozwiązania: . Licencja CC BY-NC 4.0 - kopiowanie i przeróbki do celów niekomercyjnych, z podaniem autora i źródła (link do tej strony) (zasady wykorzystania). Treść arkusza i klucza oceniania pochodzi z CKE.

Potwierdzenie

Informacja