Przejdź do głównej treści
EE.09-01-21.06-SGCzerwiec 2021 · 38 kroków · ok. 77 min · 34 kryteria z klucza

Rozwiązanie krok po kroku: Portal społecznościowy - lista przyjaciół (Wersja podstawowa)

Strona „moje konto” portalu społecznościowego: baza dane z tabelami osoby i hobby z pliku CKE, cztery zapytania (warunek z kilkoma wartościami, złączenie JOIN, LIMIT i CREATE TABLE), zdjęcie wykadrowane do kwadratu 100 × 100 px oraz strona lista.php, na której skrypt PHP wypisuje znajomych - dla każdej osoby blok ze zdjęciem w kółku, blok z imieniem, nazwiskiem i ostatnim wpisem oraz linię oddzielającą.

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-04-21.06 (panel administratora portalu): 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ą. Skrypt jest najpierw napisany najprościej, funkcjami mysqli z tabeli 1 arkusza, a na końcu zabezpieczony przed wpisami zawierającymi HTML.

To jest wersja podstawowa. W zakładce „Nowoczesny kod (flex, PDO)” jest drugi sposób rozwiązania tego samego arkusza: flexbox zamiast float, karty znajomych w <article>, PDO 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 zad1.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).

Jak liczą się punkty. Klucz ma 34 kryteria (R.1.1 - R.5.7), każde za 1 punkt. Próg zdania części praktycznej to 75%, czyli 26 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 34 kryteriów (pkt)

    Krok 1: Folder zdającego i archiwum zad1

    ok. 2 min
    Polecenie z arkusza

    Na pulpicie znajduje się archiwum ZIP o nazwie zad1.zip zabezpieczone hasłem: List@Przyjaciol& 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 zad1.zip otwierasz programem 7-Zip (albo innym programem do archiwów ZIP) i rozpakowujesz do tego folderu, podając hasło List@Przyjaciol& (wielkość liter, @ i & mają znaczenie). W środku jest plik dane.sql i osiem zdjęć: osoba1.jpg - osoba8.jpg.

    Arkusz podkreśla, że pliki strony muszą leżeć w tym samym folderze co zdjęcia - skrypt wstawi ich nazwy 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 dane

    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 dane

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

    Typowe błędy

    Nazwa bazy musi brzmieć dokładnie dane - skrypt PHP łączy się z bazą po nazwie (R.5.1).

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

    Kryteria:

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

    ok. 3 min
    Polecenie z arkusza

    Do bazy dane 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ę dane, 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 (nie import, nie PNG). 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: osoby z hobby 1, 2 albo 6

    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 imie, nazwisko, opis, zdjecie z tabeli osoby , dla wszystkich osób, których hobby ma id równe 1, 2, 6. W pliku z kwerendami lub na zrzucie istnieje zapis np.: SELECT imie, nazwisko, opis, zdjecie FROM osoby WHERE Hobby_id = 1 OR Hobby_id = 2 OR Hobby_id = 6; oraz wynik działania zapytania udokumentowano zrzutem, na którym widocznych jest dokładnie 13 rekordów, jedynie pola imie, nazwisko, opis, zdjecie

    ok. 4 min
    Polecenie z arkusza

    Zapisz i wykonaj zapytania SQL działające na bazie dane. 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 imie, nazwisko, opis, zdjecie z tabeli osoby, dla wszystkich osób, których hobby ma id jest jedną z wartości: 1, 2, 6

    Zaznacz bazę dane, karta SQL. Zapytanie klauzula po klauzuli:

    • SELECT imie, nazwisko, opis, zdjecie - dokładnie cztery kolumny z arkusza („jedynie” wyklucza SELECT *),
    • FROM osoby,
    • WHERE Hobby_id = 1 OR Hobby_id = 2 OR Hobby_id = 6 - identyfikator hobby siedzi w tabeli osoby, w kolumnie Hobby_id (klucz obcy do hobby.id), więc złączenie nie jest potrzebne. Trzy warunki łączy OR - wystarczy, że spełniony jest jeden.

    Wynik: 13 osób (muzyka, film i komputery), jak w kluczu. Zapytanie kopiujesz do pliku kwerendy.txt, a cały ekran zapisujesz jako kw1.png. To samo zapytanie wyśle później skrypt strony.

    Typowe błędy

    AND zamiast OR szuka osób, które mają jednocześnie trzy różne hobby - wynik jest pusty. Ten sam warunek można zapisać krócej: WHERE Hobby_id IN (1, 2, 6).

    kwerendy.txt Tekst nowy plik
    -- Zapytanie 1
    SELECT imie, nazwisko, opis, zdjecie FROM osoby WHERE Hobby_id = 1 OR Hobby_id = 2 OR Hobby_id = 6;
    Podgląd strony po tym kroku
    Podgląd strony po kroku 4
  5. Krok 5: Zapytanie 2: osoby urodzone po 2000 roku z nazwą hobby

    Kryteria:

    R.1.4 Utworzono zapytanie 2 wybierające jedynie pola id i nazwisko z tabeli osoby oraz odpowiadające im pole nazwa z tabeli hobby dla osób, które urodziły się po 2000 roku. W pliku z kwerendami lub na zrzucie istnieje zapis np.: SELECT osoby.id, nazwisko, nazwa FROM osoby JOIN hobby ON osoby.hobby_id = hobby.id WHERE rok_urodzenia > 2000; możliwe też INNER JOIN lub bez JOIN z porównaniem kluczy w warunku oraz wynik działania zapytania udokumentowano zrzutem, na którym widocznych jest dokładnie 16 rekordów, jedynie pola osoby.id, nazwisko, nazwa

    ok. 4 min
    Polecenie z arkusza

    Zapytanie 2: wybierające jedynie pola id i nazwisko z tabeli osoby oraz odpowiadające im pole nazwa z tabeli hobby dla osób, które urodziły się po 2000 roku

    • SELECT osoby.id, nazwisko, nazwa - kolumna id jest w obu tabelach, więc trzeba wskazać, z której ją brać (osoby.id); nazwisko i nazwa są jednoznaczne,
    • FROM osoby JOIN hobby ON osoby.Hobby_id = hobby.id - złączenie: do każdej osoby dołączany jest wiersz hobby o numerze z jej kolumny Hobby_id,
    • WHERE rok_urodzenia > 2000 - „po 2000 roku” to rok 2001 i późniejsze, więc znak >, nie >=.

    Wynik: 16 rekordów z trzema kolumnami, jak w kluczu. Zrzut: kw2.png.

    Typowe błędy

    Samo SELECT id, … przy złączeniu kończy się błędem #1052 („Column 'id' in field list is ambiguous”). Bez warunku ON (albo porównania kluczy w WHERE) baza zwróci każdą osobę z każdym hobby - setki wierszy.

    kwerendy.txt Tekst zmienione: 3 linie
    -- Zapytanie 1
    SELECT imie, nazwisko, opis, zdjecie FROM osoby WHERE Hobby_id = 1 OR Hobby_id = 2 OR Hobby_id = 6;
    
    -- Zapytanie 2
    SELECT osoby.id, nazwisko, nazwa FROM osoby JOIN hobby ON osoby.Hobby_id = hobby.id WHERE rok_urodzenia > 2000;
    Podgląd strony po tym kroku
    Podgląd strony po kroku 5
  6. Krok 6: Zapytanie 3: pierwsze pięć Monik

    Kryteria:

    R.1.5 Utworzono zapytanie 3 wybierające jedynie pola id i zdjecie z tabeli osoby dla osób które mają na imię Monika. Kwerenda wybiera początkowe 5 wierszy, należy jawnie wskazać liczbę wierszy. W pliku z kwerendami lub na zrzucie istnieje zapis np.: SELECT id, zdjecie FROM osoby WHERE imie='Monika' LIMIT 5; oraz wynik działania zapytania udokumentowano zrzutem, na którym widocznych jest dokładnie 5 rekordów, dane: 2 osoba1.jpg; 4 osoba2.jpg; 7 osoba1.jpg; 12 osoba1.jpg; 17 osoba4.jpg

    ok. 2 min
    Polecenie z arkusza

    Zapytanie 3: wybierające jedynie pola id i zdjecie z tabeli osoby dla osób, które mają na imię Monika. Kwerenda wybiera pierwsze 5 wierszy, należy jawnie wskazać liczbę wierszy

    • SELECT id, zdjecie FROM osoby,
    • WHERE imie = 'Monika' - napis w apostrofach,
    • LIMIT 5 - „jawnie wskazana liczba wierszy”: baza zwraca najwyżej pięć pierwszych pasujących rekordów.

    Monik jest w tabeli więcej niż pięć, a phpMyAdmin i tak sam dopisałby LIMIT 0, 25 - dlatego arkusz każe wpisać limit w zapytaniu. Wynik: 2 osoba1.jpg, 4 osoba2.jpg, 7 osoba1.jpg, 12 osoba1.jpg, 17 osoba4.jpg - dokładnie te pary wymienia klucz. Zrzut: kw3.png.

    kwerendy.txt Tekst zmienione: 3 linie
    -- Zapytanie 1
    SELECT imie, nazwisko, opis, zdjecie FROM osoby WHERE Hobby_id = 1 OR Hobby_id = 2 OR Hobby_id = 6;
    
    -- Zapytanie 2
    SELECT osoby.id, nazwisko, nazwa FROM osoby JOIN hobby ON osoby.Hobby_id = hobby.id WHERE rok_urodzenia > 2000;
    
    -- Zapytanie 3
    SELECT id, zdjecie FROM osoby WHERE imie = 'Monika' LIMIT 5;
    Podgląd strony po tym kroku
    Podgląd strony po kroku 6
  7. Krok 7: Zapytanie 4: tabela wpisy

    Kryteria:

    R.1.6 Utworzono zapytanie 4 tworzące tabelę o nazwie wpisy , kluczu głównym id typu całkowitego dodatniego oraz polach wpis typu tekstowego i uzytkownik_id typu całkowitego dodatniego. Klucz główny i pole uzytkownik_id nie mogą przyjmować wartości pustych. Klucz główny powinien być jawnie zapisany oraz automatycznie inkrementowany. W pliku z kwerendami lub na zrzucie istnieje zapis np.: CREATE TABLE wpisy ( id INTEGER UNSIGNED NOT NULL AUTO_INCREMENT, wpis TEXT, (dopuszczalna dowolna nazwa dla pola tekstowego) uzytkownik_id INTEGER UNSIGNED NOT NULL, PRIMARY KEY(id) ); (dowolne typy całkowite i tekstowe) oraz wynik działania zapytania udokumentowano zrzutem, na którym widoczny jest komunikat o poprawnie wykonanej kwerendzie lub utworzona tabela

    ok. 4 min
    Polecenie z arkusza

    Zapytanie 4: tworzące tabelę o nazwie wpisy z następującymi polami: id, klucz główny jawnie zapisany, typu całkowitego dodatniego, automatycznie inkrementowany, nie może przyjmować wartości pustych; wpis typu tekstowego; uzytkownik_id typu całkowitego dodatniego, nie może przyjmować wartości pustych.

    Każde wymaganie ma w zapytaniu swoje słowo:

    • id INT UNSIGNED NOT NULL AUTO_INCREMENT, - INT to typ całkowity, UNSIGNED - bez znaku, czyli tylko liczby nieujemne („dodatni”), NOT NULL - pole nie może być puste, AUTO_INCREMENT - baza sama nada kolejny numer,
    • wpis TEXT, - typ tekstowy na dłuższy wpis,
    • uzytkownik_id INT UNSIGNED NOT NULL, - liczba całkowita dodatnia, obowiązkowa,
    • PRIMARY KEY (id) - klucz główny zapisany jawnie, osobną klauzulą.

    phpMyAdmin odpowiada „MySQL zwrócił pusty wynik” - CREATE TABLE niczego nie wybiera, a w lewym panelu pojawia się tabela wpisy. Zrzut: kw4.png. Plik kwerendy.txt ma komplet czterech zapytań.

    Typowe błędy

    AUTO_INCREMENT działa tylko na kolumnie, która jest kluczem - bez PRIMARY KEY (id) baza zgłosi błąd #1075.

    kwerendy.txt Tekst zmienione: 8 linii
    -- Zapytanie 1
    SELECT imie, nazwisko, opis, zdjecie FROM osoby WHERE Hobby_id = 1 OR Hobby_id = 2 OR Hobby_id = 6;
    
    -- Zapytanie 2
    SELECT osoby.id, nazwisko, nazwa FROM osoby JOIN hobby ON osoby.Hobby_id = hobby.id WHERE rok_urodzenia > 2000;
    
    -- Zapytanie 3
    SELECT id, zdjecie FROM osoby WHERE imie = 'Monika' LIMIT 5;
    
    -- Zapytanie 4
    CREATE TABLE wpisy (
        id INT UNSIGNED NOT NULL AUTO_INCREMENT,
        wpis TEXT,
        uzytkownik_id INT UNSIGNED NOT NULL,
        PRIMARY KEY (id)
    );
    Podgląd strony po tym kroku
    Podgląd strony po kroku 7
  8. Etap 2: Grafika i strona HTML

    Kroki 8-20 · po tym etapie masz 16 z 34 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 strona pokazuje zdjęcia w kółku, więc potrzebny jest kwadrat. 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 - klucz wymaga proporcji 1:1 uzyskanej kadrem.

    Podgląd strony po tym kroku
    Podgląd strony po kroku 9
  10. Krok 10: Plik lista.php

    Kryteria:

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

    ok. 2 min
    Polecenie z arkusza

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

    Plik lista.php w folderze zdającego, obok zdjęć. Rozszerzenie .php, bo dojdzie skrypt - 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) - lista.html albo index.php to strata punktu.

    lista.php PHP nowy plik
    <!DOCTYPE html>
    <html lang="pl">
    <head>
    </head>
    <body>
    </body>
    </html>
    Podgląd strony po tym kroku (lista.php)
  11. Krok 11: 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 „przyjaciół” mogą wyświetlić się jako krzaki. Plik trzeba też zapisać w UTF-8 (w Notepad++ menu Kodowanie).

    lista.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 (lista.php)
  12. Krok 12: Tytuł strony

    Kryteria:

    R.2.4 Nadano tytuł strony: "Lista przyjaciół”

    ok. 1 min
    Polecenie z arkusza

    Tytuł strony widoczny na karcie przeglądarki: „Lista przyjaciół”

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

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

    Kryteria:

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

    ok. 1 min
    Polecenie z arkusza

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

    <link rel="stylesheet" href="styl.css"> w <head>. Plik stylów powstanie po HTML-u; całe formatowanie ma pochodzić tylko z niego, bez atrybutów style w HTML-u.

    Typowe błędy

    Klucz uznaje R.3.3 tylko przy działającym połączeniu, w którym wszystkie selektory trafiają w bloki - selektor klasy zapisany z # (albo identyfikatora z kropką) też odbiera punkt.

    lista.php PHP zmienione: 1 linia
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <title>Lista przyjaciół</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
    </body>
    </html>
    Podgląd strony po tym kroku (lista.php)
  14. Krok 14: Bloki: baner, główny i dwie stopki

    Kryteria:

    R.2.5 Wygląd strony zdefiniowano dzieląc ją na bloki: baner, główny i dwa bloki stopki. Zastosowano znaczniki sekcji

    ok. 2 min
    Polecenie z arkusza

    Podział strony na bloki umiejscowione jeden pod drugim: baner, główny i dwa obok siebie bloki stopki. 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 główny <section> i dwie stopki <footer>. Blok główny dostaje identyfikator main (po angielsku - arkusz go nie narzuca), bo to on będzie miał tło, wysokość i paski przewijania. Obie stopki wyglądają tak samo, więc wystarczy im wspólny selektor znacznika footer - identyfikatory nie są potrzebne. Bloki zdjęcie, opis i linia nie stoją w pliku na stałe - wygeneruje je skrypt dla każdej osoby.

    Na razie bloki są puste i stoją jeden pod drugim; stopki ustawi obok siebie CSS.

    lista.php PHP zmienione: 8 linii
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <title>Lista przyjaciół</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <header>
        </header>
        <section id="main">
        </section>
        <footer>
        </footer>
        <footer>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (lista.php)
  15. Krok 15: Baner: nagłówek pierwszego stopnia

    ok. 1 min
    Polecenie z arkusza

    Zawartość banera: nagłówek pierwszego stopnia o treści „Portal Społecznościowy - moje konto”

    <h1> w <header> - jedyny nagłówek pierwszego stopnia na stronie.

    lista.php PHP zmienione: 1 linia
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <title>Lista przyjaciół</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <header>
            <h1>Portal Społecznościowy - moje konto</h1>
        </header>
        <section id="main">
        </section>
        <footer>
        </footer>
        <footer>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (lista.php)
  16. Krok 16: Blok główny: nagłówek „Moje zainteresowania”

    ok. 1 min
    Polecenie z arkusza

    Zawartość bloku głównego: Nagłówek drugiego stopnia o treści „Moje zainteresowania”

    Drugiego stopnia to <h2>. Klucz R.2.6 sprawdza go razem z <h1> banera i drugim <h2> - punkt przyjdzie po kroku z „Moi znajomi”.

    lista.php PHP zmienione: 1 linia
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <title>Lista przyjaciół</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <header>
            <h1>Portal Społecznościowy - moje konto</h1>
        </header>
        <section id="main">
            <h2>Moje zainteresowania</h2>
        </section>
        <footer>
        </footer>
        <footer>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (lista.php)
  17. Krok 17: Lista punktowana zainteresowań

    Kryteria:

    R.2.7 W bloku głównym umieszczono listę punktowaną z trzema elementami, znaczniki <ul>, <li> oraz ich zamknięcia

    ok. 1 min
    Polecenie z arkusza

    Lista punktowana (nieuporządkowana) z elementami: muzyka, film, komputery

    Lista nieuporządkowana to <ul> (unordered list), każdy element w <li>. Kropki przed elementami dopisuje przeglądarka.

    Typowe błędy

    <ol> to lista numerowana - klucz wymaga znaczników <ul> i <li> oraz ich zamknięć.

    lista.php PHP zmienione: 5 linii
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <title>Lista przyjaciół</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <header>
            <h1>Portal Społecznościowy - moje konto</h1>
        </header>
        <section id="main">
            <h2>Moje zainteresowania</h2>
            <ul>
                <li>muzyka</li>
                <li>film</li>
                <li>komputery</li>
            </ul>
        </section>
        <footer>
        </footer>
        <footer>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (lista.php)
  18. Krok 18: Blok główny: nagłówek „Moi znajomi”

    Kryteria:

    R.2.6 W bloku banera zapisano nagłówek h1: "Portal Społecznościowy - moje konto" oraz w bloku głównym nagłówki h2: "Moje zainteresowania" i "Moi znajomi"

    ok. 1 min
    Polecenie z arkusza

    Nagłówek drugiego stopnia o treści „Moi znajomi”

    Drugi <h2>, pod listą. Pod nim skrypt wypisze znajomych. Strona ma już nagłówek <h1> w banerze i oba nagłówki <h2> (R.2.6).

    lista.php PHP zmienione: 1 linia
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <title>Lista przyjaciół</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <header>
            <h1>Portal Społecznościowy - moje konto</h1>
        </header>
        <section id="main">
            <h2>Moje zainteresowania</h2>
            <ul>
                <li>muzyka</li>
                <li>film</li>
                <li>komputery</li>
            </ul>
            <h2>Moi znajomi</h2>
        </section>
        <footer>
        </footer>
        <footer>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (lista.php)
  19. Krok 19: Pierwsza stopka: autor strony

    Kryteria:

    R.2.8 W pierwszym bloku stopki umieszczono numer PESEL zdającego

    ok. 1 min
    Polecenie z arkusza

    Zawartość pierwszego bloku 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.

    lista.php PHP zmienione: 1 linia
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <title>Lista przyjaciół</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <header>
            <h1>Portal Społecznościowy - moje konto</h1>
        </header>
        <section id="main">
            <h2>Moje zainteresowania</h2>
            <ul>
                <li>muzyka</li>
                <li>film</li>
                <li>komputery</li>
            </ul>
            <h2>Moi znajomi</h2>
        </section>
        <footer>
            Stronę wykonał: Bartosz Bryniarski
        </footer>
        <footer>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (lista.php)
  20. Krok 20: Druga stopka: odnośnik pocztowy

    Kryteria:

    R.3.2 Na stronie umieszczono odnośnik pocztowy "napisz do mnie" łączący z adresem email (mailto:[email protected])

    ok. 1 min
    Polecenie z arkusza

    Zawartość drugiego bloku stopki: odnośnik pocztowy o treści „napisz do mnie” prowadzący do adresu „[email protected]”

    Odnośnik pocztowy ma w href przedrostek mailto: - kliknięcie otwiera program pocztowy z wpisanym adresatem [email protected], zamiast przechodzić do innej strony (R.3.2).

    Typowe błędy

    href="[email protected]" bez mailto: przeglądarka potraktuje jak nazwę pliku w folderze strony i pokaże błąd 404.

    lista.php PHP zmienione: 1 linia
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <title>Lista przyjaciół</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <header>
            <h1>Portal Społecznościowy - moje konto</h1>
        </header>
        <section id="main">
            <h2>Moje zainteresowania</h2>
            <ul>
                <li>muzyka</li>
                <li>film</li>
                <li>komputery</li>
            </ul>
            <h2>Moi znajomi</h2>
        </section>
        <footer>
            Stronę wykonał: Bartosz Bryniarski
        </footer>
        <footer>
            <a href="mailto:[email protected]">napisz do mnie</a>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (lista.php)
  21. Etap 3: Styl CSS

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

    Krok 21: Plik styl.css: krój Georgia dla całej strony

    Kryteria:

    R.4.1 Ustawiono domyślny krój czcionki dla całej strony na Georgia (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 Georgia

    Nowy plik styl.css w folderze zdającego. Pierwsza reguła: selektor uniwersalny * z font-family: Georgia - krój dostaje każdy element strony. Klucz R.4.1 przyjmuje też body albo html.

    styl.css CSS nowy plik
    * {
        font-family: Georgia;
    }
    Podgląd strony po tym kroku (lista.php)
  22. Krok 22: Baner: tło, kolor, wyśrodkowanie, rozmiar czcionki, wysokość

    Kryteria:

    R.4.8 Ustawiono rozmiar czcionki banera na 50%

    ok. 2 min
    Polecenie z arkusza

    Dla banera: kolor tła #005B4F, biały kolor czcionki, wyrównanie tekstu do środka, rozmiar czcionki 50%, wysokość 20 px

    Selektor znacznika header - na stronie jest jeden baner. font-size: 50% zmniejsza czcionkę o połowę względem rodzica: nagłówek <h1> liczy swój rozmiar (2em) od banera, więc zamiast 32 px ma 16 px i mieści się w pasku o wysokości 20 px (R.4.8).

    styl.css CSS zmienione: 7 linii
    * {
        font-family: Georgia;
    }
    header {
        background-color: #005B4F;
        color: white;
        text-align: center;
        font-size: 50%;
        height: 20px;
    }
    Podgląd strony po tym kroku (lista.php)
  23. Krok 23: Blok główny: tło, wysokość, marginesy wewnętrzne, paski przewijania

    Kryteria:

    R.4.9 Ustawiono przynajmniej jeden pasek przewijania (przesuwania) dla bloku głównego, np. overflow: scroll; (lub auto)

    ok. 2 min
    Polecenie z arkusza

    Dla bloku głównego: kolor tła #E1E2E1, wysokość 400px, marginesy wewnętrzne 20 px, paski przesuwania (scroll)

    Selektor identyfikatora #main. Znajomych jest trzynaścioro, a blok ma tylko 400 px wysokości - overflow: scroll dokłada paski przewijania, więc treść, która się nie mieści, przewija się wewnątrz bloku, a stopki zostają na swoim miejscu (R.4.9). padding: 20px odsuwa treść od brzegów bloku; dolicza się do wysokości, więc blok zajmuje na ekranie 440 px.

    Typowe błędy

    Bez overflow treść wylewa się poza szare tło na stopki i dalej w dół strony.

    styl.css CSS zmienione: 6 linii
    * {
        font-family: Georgia;
    }
    header {
        background-color: #005B4F;
        color: white;
        text-align: center;
        font-size: 50%;
        height: 20px;
    }
    #main {
        background-color: #E1E2E1;
        height: 400px;
        padding: 20px;
        overflow: scroll;
    }
    Podgląd strony po tym kroku (lista.php)
  24. Krok 24: Blok zdjęcie: szerokość 20%

    ok. 1 min
    Polecenie z arkusza

    Dla bloku zdjęcie: szerokość 20%

    Bloków ze zdjęciem będzie tyle, ilu znajomych, a identyfikator może wystąpić na stronie tylko raz - dlatego skrypt nada im klasę photo, a w CSS selektor klasy zaczyna się od kropki: .photo. Szerokość 20% liczy się od szerokości bloku głównego. Na razie na stronie nie ma żadnego takiego bloku - reguła zadziała, gdy wypisze je skrypt.

    styl.css CSS zmienione: 3 linie
    * {
        font-family: Georgia;
    }
    header {
        background-color: #005B4F;
        color: white;
        text-align: center;
        font-size: 50%;
        height: 20px;
    }
    #main {
        background-color: #E1E2E1;
        height: 400px;
        padding: 20px;
        overflow: scroll;
    }
    .photo {
        width: 20%;
    }
    Podgląd strony po tym kroku (lista.php)
  25. Krok 25: Blok opis obok zdjęcia

    ok. 1 min
    Polecenie z arkusza

    Dla bloku opis: blok jest wyświetlany obok zdjęcia

    Blok zdjęcia i blok opisu (klasa description) dostają float: left - pierwszy staje przy lewej krawędzi, drugi tuż obok niego. Bez float każdy blok zajmuje całą szerokość i opis spadłby pod zdjęcie.

    styl.css CSS zmienione: 3 linie
    * {
        font-family: Georgia;
    }
    header {
        background-color: #005B4F;
        color: white;
        text-align: center;
        font-size: 50%;
        height: 20px;
    }
    #main {
        background-color: #E1E2E1;
        height: 400px;
        padding: 20px;
        overflow: scroll;
    }
    .photo {
        width: 20%;
    }
    .photo, .description {
        float: left;
    }
    Podgląd strony po tym kroku (lista.php)
  26. Krok 26: Blok linia pod zdjęciem i opisem

    ok. 1 min
    Polecenie z arkusza

    Dla bloku linia: linia jest wyświetlana pod zdjęciem i opisem zgodnie z obrazem 2

    clear: both każe blokowi linii zacząć się dopiero pod oboma pływającymi blokami. Bez tego kolejna osoba wcisnęłaby się obok poprzedniej, a linia stanęłaby w połowie wysokości zdjęcia.

    styl.css CSS zmienione: 3 linie
    * {
        font-family: Georgia;
    }
    header {
        background-color: #005B4F;
        color: white;
        text-align: center;
        font-size: 50%;
        height: 20px;
    }
    #main {
        background-color: #E1E2E1;
        height: 400px;
        padding: 20px;
        overflow: scroll;
    }
    .photo {
        width: 20%;
    }
    .photo, .description {
        float: left;
    }
    .line {
        clear: both;
    }
    Podgląd strony po tym kroku (lista.php)
  27. Krok 27: Obie stopki: tło, kolor, wyśrodkowanie, wymiary i układ obok siebie

    Kryteria: , ,

    R.3.1 Układ bloków po uruchomieniu strony w przeglądarce jest zgodny z Obrazem 2 w arkuszu egzaminacyjnym (nie uwzględnia się zestawu bloków zawierających: zdjecie, opis, linia)

    R.4.4 Ustawiono wysokość bloków dla banera i stopek na 20px oraz bloku głównego na 400px

    R.4.5 Ustawiono szerokość stopek na 50% oraz bloku zawierającego zdjęcie na 20%

    ok. 3 min
    Polecenie z arkusza

    Dla obu bloków stopki: kolor tła #005B4F, biały kolor czcionki, wyrównanie tekstu do środka, szerokość 50%, wysokość 20 px

    Jedna reguła dla znacznika footer obejmuje obie stopki. Dwie szerokości po 50% to razem 100%, a float: left stawia drugą stopkę obok pierwszej zamiast pod nią - tak jak na obrazie 2 (R.3.1). Arkusz nie podaje tej właściwości, ale wymaga układu z obrazu; stopki nie mają marginesów ani obramowań, więc obie mieszczą się w jednym rzędzie.

    Wysokości banera, stopek i bloku głównego (R.4.4) oraz szerokości stopek i bloku zdjęcia (R.4.5) są ustawione.

    Typowe błędy

    Dowolny margin albo border na stopce przy szerokości 50% zepchnie drugą stopkę pod pierwszą.

    styl.css CSS zmienione: 8 linii
    * {
        font-family: Georgia;
    }
    header {
        background-color: #005B4F;
        color: white;
        text-align: center;
        font-size: 50%;
        height: 20px;
    }
    #main {
        background-color: #E1E2E1;
        height: 400px;
        padding: 20px;
        overflow: scroll;
    }
    .photo {
        width: 20%;
    }
    .photo, .description {
        float: left;
    }
    .line {
        clear: both;
    }
    footer {
        background-color: #005B4F;
        color: white;
        text-align: center;
        width: 50%;
        height: 20px;
        float: left;
    }
    Podgląd strony po tym kroku (lista.php)
  28. Krok 28: Obraz: marginesy wewnętrzne i zaokrąglenie do koła

    Kryteria: ,

    R.4.7 Ustawiono marginesy wewnętrzne (padding) dla bloku głównego i selektora img na 20px

    R.4.10 Ustawiono zakrzywienie obramowania 100% dla obrazu, np. border-radius: 100%; poprawne również dla wartości z przedziału <50%, 100%)

    ok. 2 min
    Polecenie z arkusza

    Dla selektora obrazu: marginesy wewnętrzne 20 px, zakrzywienie obramowania 100% (tak, że obraz jest wyświetlany w kształcie koła)

    Selektor znacznika img. border-radius: 100% zaokrągla rogi tak mocno, że kwadratowe zdjęcie 100 × 100 px wyświetla się jako koło (każda wartość od 50% w górę daje ten sam efekt - klucz przyjmuje przedział od 50% do 100%). padding: 20px odsuwa zdjęcie od sąsiednich bloków. Marginesy wewnętrzne bloku głównego i obrazu są ustawione (R.4.7).

    Typowe błędy

    Kryterium R.4.7 jest spełnione tylko przy selektorze znacznika img - reguła dla klasy (np. .photo img albo .avatar) według uwagi w kluczu go nie spełnia.

    styl.css CSS zmienione: 4 linie
    * {
        font-family: Georgia;
    }
    header {
        background-color: #005B4F;
        color: white;
        text-align: center;
        font-size: 50%;
        height: 20px;
    }
    #main {
        background-color: #E1E2E1;
        height: 400px;
        padding: 20px;
        overflow: scroll;
    }
    .photo {
        width: 20%;
    }
    .photo, .description {
        float: left;
    }
    .line {
        clear: both;
    }
    footer {
        background-color: #005B4F;
        color: white;
        text-align: center;
        width: 50%;
        height: 20px;
        float: left;
    }
    img {
        padding: 20px;
        border-radius: 100%;
    }
    Podgląd strony po tym kroku (lista.php)
  29. Krok 29: Nagłówki drugiego stopnia: wyśrodkowanie i tło

    Kryteria: ,

    R.4.2 Ustawiono kolor tła #005B4F dla banera i stopek, #E1E2E1 dla bloku głównego oraz #00897B dla selektora h2

    R.4.6 Ustawiono wyrównanie tekstu do środka dla banera i stopek oraz dla selektora h2

    ok. 1 min
    Polecenie z arkusza

    Dla selektora nagłówka drugiego stopnia: wyrównanie tekstu do środka, tło #00897B

    Selektor h2 obejmuje oba nagłówki bloku głównego. Kolory tła wszystkich elementów (R.4.2) i wyśrodkowanie banera, stopek i nagłówków (R.4.6) są ustawione.

    styl.css CSS zmienione: 4 linie
    * {
        font-family: Georgia;
    }
    header {
        background-color: #005B4F;
        color: white;
        text-align: center;
        font-size: 50%;
        height: 20px;
    }
    #main {
        background-color: #E1E2E1;
        height: 400px;
        padding: 20px;
        overflow: scroll;
    }
    .photo {
        width: 20%;
    }
    .photo, .description {
        float: left;
    }
    .line {
        clear: both;
    }
    footer {
        background-color: #005B4F;
        color: white;
        text-align: center;
        width: 50%;
        height: 20px;
        float: left;
    }
    img {
        padding: 20px;
        border-radius: 100%;
    }
    h2 {
        text-align: center;
        background-color: #00897B;
    }
    Podgląd strony po tym kroku (lista.php)
  30. Krok 30: Odnośnik: biały kolor czcionki

    Kryteria:

    R.4.3 Ustawiono biały kolor czcionki dla banera i stopek oraz selektora a

    ok. 1 min
    Polecenie z arkusza

    Dla selektora odnośnika: biały kolor czcionki

    Odnośnik nie dziedziczy koloru po stopce - przeglądarka maluje go własnym niebieskim (a po kliknięciu fioletowym), który na zielonym tle jest prawie niewidoczny. Reguła dla a daje biały (R.4.3). Arkusz stylów jest kompletny.

    styl.css CSS zmienione: 3 linie
    * {
        font-family: Georgia;
    }
    header {
        background-color: #005B4F;
        color: white;
        text-align: center;
        font-size: 50%;
        height: 20px;
    }
    #main {
        background-color: #E1E2E1;
        height: 400px;
        padding: 20px;
        overflow: scroll;
    }
    .photo {
        width: 20%;
    }
    .photo, .description {
        float: left;
    }
    .line {
        clear: both;
    }
    footer {
        background-color: #005B4F;
        color: white;
        text-align: center;
        width: 50%;
        height: 20px;
        float: left;
    }
    img {
        padding: 20px;
        border-radius: 100%;
    }
    h2 {
        text-align: center;
        background-color: #00897B;
    }
    a {
        color: white;
    }
    Podgląd strony po tym kroku (lista.php)
  31. Etap 4: Skrypt PHP

    Kroki 31-36 · po tym etapie masz 34 z 34 kryteriów (pkt)

    Krok 31: Miejsce skryptu i połączenie z bazą dane

    Kryteria:

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

    ok. 3 min
    Polecenie z arkusza

    Efekt działania skryptu. Skrypt: Napisany w języku PHP. Skrypt łączy się z serwerem bazy danych na localhost, użytkownik root bez hasła, baza danych o nazwie dane

    „Efekt działania skryptu” ma być w bloku głównym, pod nagłówkiem „Moi znajomi” (obraz 2) - tam więc piszesz 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 dane. Czwarty parametr od razu wybiera bazę, więc mysqli_select_db nie jest potrzebne. Połączenie trafia do zmiennej $connection (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.

    lista.php PHP zmienione: 3 linie
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <title>Lista przyjaciół</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <header>
            <h1>Portal Społecznościowy - moje konto</h1>
        </header>
        <section id="main">
            <h2>Moje zainteresowania</h2>
            <ul>
                <li>muzyka</li>
                <li>film</li>
                <li>komputery</li>
            </ul>
            <h2>Moi znajomi</h2>
    <?php
    $connection = mysqli_connect('localhost', 'root', '', 'dane');
    ?>
        </section>
        <footer>
            Stronę wykonał: Bartosz Bryniarski
        </footer>
        <footer>
            <a href="mailto:[email protected]">napisz do mnie</a>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (lista.php)
  32. Krok 32: Zapytanie 1 wysłane do bazy

    Kryteria:

    R.5.3 Skrypt wysyła do bazy danych zapytanie 1

    ok. 2 min
    Polecenie z arkusza

    Wysyła do bazy danych zapytanie 1

    mysqli_query($connection, '…') wysyła do bazy zapytanie 1 skopiowane z kwerendy.txt (R.5.3). Zapytanie stoi w apostrofach PHP, bo samo nie zawiera apostrofów. Wynik - zbiór 13 wierszy - trafia do zmiennej $result; strona jeszcze niczego nie wypisuje.

    lista.php PHP zmienione: 1 linia
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <title>Lista przyjaciół</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <header>
            <h1>Portal Społecznościowy - moje konto</h1>
        </header>
        <section id="main">
            <h2>Moje zainteresowania</h2>
            <ul>
                <li>muzyka</li>
                <li>film</li>
                <li>komputery</li>
            </ul>
            <h2>Moi znajomi</h2>
    <?php
    $connection = mysqli_connect('localhost', 'root', '', 'dane');
    $result = mysqli_query($connection, 'SELECT imie, nazwisko, opis, zdjecie FROM osoby WHERE Hobby_id = 1 OR Hobby_id = 2 OR Hobby_id = 6;');
    ?>
        </section>
        <footer>
            Stronę wykonał: Bartosz Bryniarski
        </footer>
        <footer>
            <a href="mailto:[email protected]">napisz do mnie</a>
        </footer>
    </body>
    </html>

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

  33. Krok 33: Pętla po wierszach i blok zdjęcie

    Kryteria: ,

    R.5.5 Wyświetlono obraz o nazwie pobranej z bazy danych oraz tekście alternatywnym „przyjaciel”

    R.5.7 Wyświetlono wszystkie wiersze zwrócone zapytaniem w oparciu o pętlę

    ok. 4 min
    Polecenie z arkusza

    Dane z każdego zwróconego zapytaniem wiersza podzielone są na trzy bloki: blok zdjęcie, w którym jest wyświetlony obraz o nazwie pobranej z bazy danych oraz tekście alternatywnym „przyjaciel”

    • 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] imię, $row[1] nazwisko, $row[2] opis, $row[3] zdjęcie. Gdy wierszy zabraknie, zwraca false i pętla się kończy - przechodzi więc przez wszystkie 13 osób (R.5.7),
    • echo wypisuje blok z klasą photo, a w nim <img>: nazwa pliku z bazy w src (doklejona operatorem .), stały tekst alternatywny „przyjaciel” (R.5.5).

    Podgląd: 13 zdjęć w kółku jedno pod drugim. Pływają do lewej krawędzi, bo blok opisu jeszcze nie istnieje.

    Typowe błędy

    if zamiast while wypisze tylko pierwszą osobę - klucz wymaga wszystkich wierszy w oparciu o pętlę (R.5.7).

    lista.php PHP zmienione: 3 linie
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <title>Lista przyjaciół</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <header>
            <h1>Portal Społecznościowy - moje konto</h1>
        </header>
        <section id="main">
            <h2>Moje zainteresowania</h2>
            <ul>
                <li>muzyka</li>
                <li>film</li>
                <li>komputery</li>
            </ul>
            <h2>Moi znajomi</h2>
    <?php
    $connection = mysqli_connect('localhost', 'root', '', 'dane');
    $result = mysqli_query($connection, 'SELECT imie, nazwisko, opis, zdjecie FROM osoby WHERE Hobby_id = 1 OR Hobby_id = 2 OR Hobby_id = 6;');
    while ($row = mysqli_fetch_row($result)) {
        echo '<section class="photo"><img src="' . $row[3] . '" alt="przyjaciel"></section>';
    }
    ?>
        </section>
        <footer>
            Stronę wykonał: Bartosz Bryniarski
        </footer>
        <footer>
            <a href="mailto:[email protected]">napisz do mnie</a>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (lista.php)
  34. Krok 34: Blok opis: imię i nazwisko oraz ostatni wpis

    Kryteria:

    R.5.6 Wyświetlono nagłówek trzeciego stopnia z imieniem i nazwiskiem pobranym z bazy danych oraz paragraf (akapit) o treści: „Ostatni wpis: <opis>”, gdzie pole <opis> jest pobrane z bazy danych

    ok. 3 min
    Polecenie z arkusza

    blok opis, w którym jest wyświetlony nagłówek trzeciego stopnia z imieniem i nazwiskiem pobranym z bazy danych oraz paragraf (akapit) o treści: „Ostatni wpis: <opis>”, gdzie pole <opis> jest pobrane z bazy danych

    Drugi echo w tej samej pętli: blok z klasą description, w nim nagłówek <h3> z imieniem i nazwiskiem rozdzielonymi spacją ($row[0] . ' ' . $row[1]) i paragraf <p> z napisem „Ostatni wpis: ” i opisem z bazy (R.5.6).

    Podgląd: opis stoi obok zdjęcia, jak na obrazie 2 - pierwsza osoba to Monika Kowalska z wpisem „Z checia Ciebie poznam”. Brak polskich liter w opisach („checia”, a u Moniki Kopacz „dzi? rano 5 km”) pochodzi z pliku dane.sql z archiwum CKE - znaki zapytania w miejscu „ś” i „ą” są w nim zapisane dosłownie, skrypt niczego nie psuje.

    lista.php PHP zmienione: 1 linia
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <title>Lista przyjaciół</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <header>
            <h1>Portal Społecznościowy - moje konto</h1>
        </header>
        <section id="main">
            <h2>Moje zainteresowania</h2>
            <ul>
                <li>muzyka</li>
                <li>film</li>
                <li>komputery</li>
            </ul>
            <h2>Moi znajomi</h2>
    <?php
    $connection = mysqli_connect('localhost', 'root', '', 'dane');
    $result = mysqli_query($connection, 'SELECT imie, nazwisko, opis, zdjecie FROM osoby WHERE Hobby_id = 1 OR Hobby_id = 2 OR Hobby_id = 6;');
    while ($row = mysqli_fetch_row($result)) {
        echo '<section class="photo"><img src="' . $row[3] . '" alt="przyjaciel"></section>';
        echo '<section class="description"><h3>' . $row[0] . ' ' . $row[1] . '</h3><p>Ostatni wpis: ' . $row[2] . '</p></section>';
    }
    ?>
        </section>
        <footer>
            Stronę wykonał: Bartosz Bryniarski
        </footer>
        <footer>
            <a href="mailto:[email protected]">napisz do mnie</a>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (lista.php)
  35. Krok 35: Blok linia

    Kryteria:

    R.5.4 Dane zwróconego zapytaniem wiersza są podzielone na bloki zawierające: zdjęcie i opis obok siebie, pod spodem linia. W przypadku linii dopuszcza się użycie jej bez znacznika bloku. Zapis jest poprawny składniowo.

    ok. 2 min
    Polecenie z arkusza

    blok linia, w którym jest wyświetlona linia pozioma

    Trzeci echo: blok z klasą line, a w nim linia pozioma <hr> (bez znacznika zamykającego). Dzięki clear: both z CSS linia staje pod zdjęciem i opisem, a następna osoba zaczyna się pod nią. Każdy wiersz z bazy jest podzielony na trzy bloki: zdjęcie i opis obok siebie, pod spodem linia (R.5.4).

    Podgląd: lista znajomych jak na obrazie 2, przewijana wewnątrz szarego bloku.

    lista.php PHP zmienione: 1 linia
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <title>Lista przyjaciół</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <header>
            <h1>Portal Społecznościowy - moje konto</h1>
        </header>
        <section id="main">
            <h2>Moje zainteresowania</h2>
            <ul>
                <li>muzyka</li>
                <li>film</li>
                <li>komputery</li>
            </ul>
            <h2>Moi znajomi</h2>
    <?php
    $connection = mysqli_connect('localhost', 'root', '', 'dane');
    $result = mysqli_query($connection, 'SELECT imie, nazwisko, opis, zdjecie FROM osoby WHERE Hobby_id = 1 OR Hobby_id = 2 OR Hobby_id = 6;');
    while ($row = mysqli_fetch_row($result)) {
        echo '<section class="photo"><img src="' . $row[3] . '" alt="przyjaciel"></section>';
        echo '<section class="description"><h3>' . $row[0] . ' ' . $row[1] . '</h3><p>Ostatni wpis: ' . $row[2] . '</p></section>';
        echo '<section class="line"><hr></section>';
    }
    ?>
        </section>
        <footer>
            Stronę wykonał: Bartosz Bryniarski
        </footer>
        <footer>
            <a href="mailto:[email protected]">napisz do mnie</a>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (lista.php)
  36. Krok 36: 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) po pętli - to ostatnia operacja na bazie (R.5.2). Wiersze są już odczytane i wypisane, więc zamknięcie niczego nie ucina. Strona spełnia wszystkie kryteria arkusza. Dalej jeden krok o zabezpieczeniu - klucz go nie wymaga.

    Typowe błędy

    mysqli_close przed pętlą zamyka połączenie, zanim mysqli_fetch_row odczyta wiersze - w PHP 8 kończy się to błędem.

    lista.php PHP zmienione: 1 linia
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <title>Lista przyjaciół</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <header>
            <h1>Portal Społecznościowy - moje konto</h1>
        </header>
        <section id="main">
            <h2>Moje zainteresowania</h2>
            <ul>
                <li>muzyka</li>
                <li>film</li>
                <li>komputery</li>
            </ul>
            <h2>Moi znajomi</h2>
    <?php
    $connection = mysqli_connect('localhost', 'root', '', 'dane');
    $result = mysqli_query($connection, 'SELECT imie, nazwisko, opis, zdjecie FROM osoby WHERE Hobby_id = 1 OR Hobby_id = 2 OR Hobby_id = 6;');
    while ($row = mysqli_fetch_row($result)) {
        echo '<section class="photo"><img src="' . $row[3] . '" alt="przyjaciel"></section>';
        echo '<section class="description"><h3>' . $row[0] . ' ' . $row[1] . '</h3><p>Ostatni wpis: ' . $row[2] . '</p></section>';
        echo '<section class="line"><hr></section>';
    }
    mysqli_close($connection);
    ?>
        </section>
        <footer>
            Stronę wykonał: Bartosz Bryniarski
        </footer>
        <footer>
            <a href="mailto:[email protected]">napisz do mnie</a>
        </footer>
    </body>
    </html>

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

  37. Etap 5: Dobre praktyki (poza kluczem)

    Krok 37 · po tym etapie masz 34 z 34 kryteriów (pkt)

    Krok 37: Zabezpieczenie: htmlspecialchars na wyjściu

    ok. 4 min
    Polecenie z arkusza

    blok opis, w którym jest wyświetlony nagłówek trzeciego stopnia z imieniem i nazwiskiem pobranym z bazy danych oraz paragraf (akapit) o treści: „Ostatni wpis: <opis>”, gdzie pole <opis> jest pobrane z bazy danych

    Opis to „ostatni wpis” użytkownika portalu - tekst, który wpisał ktoś inny. Skrypt wkleja go do strony wprost, więc przeglądarka wykona każdy znacznik, który się w nim znajdzie. Sprawdzone na wersji z poprzednich kroków: po zmianie opisu Moniki Kowalskiej na <b>Hej!</b> <script>document.title='przejete'</script> wpis wyświetla się pogrubiony, a skrypt z wpisu zmienia tytuł strony. Na prawdziwym portalu taki skrypt mógłby wykraść sesję każdej osoby, która otworzy listę znajomych - to atak XSS (cross-site scripting).

    Lekarstwo: każda wartość z bazy przechodzi przez htmlspecialchars() tuż przed wypisaniem. Funkcja zamienia <, >, & i cudzysłowy na encje (&lt;, &gt;…), więc przeglądarka pokazuje je jako zwykłe znaki. Dotyczy to też nazwy pliku zdjęcia - trafia do atrybutu src w cudzysłowie. Podgląd: ten sam wpis widać dosłownie, ze znacznikami, a skrypt się nie wykonuje. Stare linie zostają w komentarzu. Na egzaminie wystarczy wersja wcześniejsza - klucz tego nie sprawdza.

    Zapytanie przygotowane (mysqli_prepare) nie jest tu potrzebne: zapytanie 1 nie zawiera żadnej danej od użytkownika.

    Typowe błędy

    htmlspecialchars przy zapisie do bazy zamiast przy wypisywaniu psuje dane (w bazie lądują encje, a inne programy pokażą &lt;b&gt;). Zasada: dane w bazie zostają surowe, kodowanie robi się na wyjściu, pod konkretne miejsce w HTML-u.

    lista.php PHP zmienione: 8 linii
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <title>Lista przyjaciół</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <header>
            <h1>Portal Społecznościowy - moje konto</h1>
        </header>
        <section id="main">
            <h2>Moje zainteresowania</h2>
            <ul>
                <li>muzyka</li>
                <li>film</li>
                <li>komputery</li>
            </ul>
            <h2>Moi znajomi</h2>
    <?php
    $connection = mysqli_connect('localhost', 'root', '', 'dane');
    $result = mysqli_query($connection, 'SELECT imie, nazwisko, opis, zdjecie FROM osoby WHERE Hobby_id = 1 OR Hobby_id = 2 OR Hobby_id = 6;');
    while ($row = mysqli_fetch_row($result)) {
        // echo '<section class="photo"><img src="' . $row[3] . '" alt="przyjaciel"></section>';
        // echo '<section class="description"><h3>' . $row[0] . ' ' . $row[1] . '</h3><p>Ostatni wpis: ' . $row[2] . '</p></section>';
        $firstName = htmlspecialchars($row[0]);
        $lastName = htmlspecialchars($row[1]);
        $description = htmlspecialchars($row[2]);
        $photo = htmlspecialchars($row[3]);
        echo '<section class="photo"><img src="' . $photo . '" alt="przyjaciel"></section>';
        echo '<section class="description"><h3>' . $firstName . ' ' . $lastName . '</h3><p>Ostatni wpis: ' . $description . '</p></section>';
        echo '<section class="line"><hr></section>';
    }
    mysqli_close($connection);
    ?>
        </section>
        <footer>
            Stronę wykonał: Bartosz Bryniarski
        </footer>
        <footer>
            <a href="mailto:[email protected]">napisz do mnie</a>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (lista.php)
  38. Etap 6: Oddanie pracy

    Krok 38 · po tym etapie masz 34 z 34 kryteriów (pkt)

    Krok 38: 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, lista.php, osoba1.jpg - osoba8.jpg, przeglądarka.txt i styl.css (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 37.

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