Przejdź do głównej treści
INF.03-11-26.01-SGStyczeń 2026 · 47 kroków · ok. 83 min · 39 kryteriów z klucza

Rozwiązanie krok po kroku: Portal kina KinoTEKA (Wersja podstawowa)

Portal kina KinoTEKA składa się z bazy kino (aktorzy, filmy i tabela filmy_aktorzy, która realizuje relację n:m między nimi), pięciu zapytań - warunek na liczbie, wybór jednego rekordu, sortowanie po dwóch polach, złączenie przez tabelę pośrednią i COUNT z GROUP BY i aliasem - oraz dwóch stron. Na index.php Skrypt 1 rysuje okrągłe awatary wszystkich aktorów, a każdy blok aktora jest odnośnikiem do aktor.php?id=…. Na aktor.php Skrypt 2 pokazuje wybranego aktora (identyfikator przychodzi metodą GET), a Skrypt 3 liczy, w ilu filmach grał.

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 z tabeli 1 arkusza (mysqli_query, mysqli_fetch_row, mysqli_num_rows), a na końcu przerobione na wersję z prawdziwych projektów: identyfikator z adresu zamieniony na liczbę, obsługa nieistniejącego aktora, zapytania przygotowane i htmlspecialchars.

Baza i awatary pochodzą z prawdziwego archiwum pliki17 (załącznik do arkusza, hasło w treści zadania). Zrzuty wyników zapytań są odtworzone z tej bazy - na egzaminie robisz je sam, z całego ekranu. Podgląd strony od kroków z PHP to wynik prawdziwego uruchomienia kodu z danego kroku w PHP 8.2 na bazie z arkusza; aktor.php pokazuje aktora z ilustracji 4, Pinto Teixeirę (id 10), a w kroku z warunkiem - Lorenzo Di Romano (id 8), który nie gra w żadnym filmie.

To jest wersja podstawowa. W zakładce „Nowoczesny kod (grid, PDO)” jest drugi sposób rozwiązania tego samego arkusza: układ na siatce CSS, kolory w zmiennych, a baza przez PDO z danymi pobranymi przed HTML-em, walidacją identyfikatora, zapytaniami przygotowanymi i htmlspecialchars od pierwszej linii - obie wersje są zgodne z kluczem.

Jak liczą się punkty. Klucz ma 39 kryteriów (R.1.1 - R.5.8), każde za 1 punkt. Próg zdania części praktycznej to 75%, czyli 30 punktów - można stracić 9 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-8 · po tym etapie masz 7 z 39 kryteriów (pkt)

    Krok 1: Baza danych kino

    ok. 2 min
    Polecenie z arkusza

    Utwórz bazę danych o nazwie kino, z zestawem polskich znaków (np. utf8_unicode_ci)

    Najpierw archiwum pliki17.7z z pulpitu (hasło @ktorzy+f1Lmy - małpa zamiast „a”, cyfra 1 zamiast „i”, wielkość liter ma znaczenie) i folder z numerem zdającego. W phpMyAdmin: Nowa, nazwa kino, porównywanie utf8_unicode_ci. Tabele z kino.sql mają w definicji własne porównywanie utf8mb4_unicode_ci i to ono działa w zapytaniu 3: „Élodie” i „Jímenez” sortują się jak zwykłe „E” i „i”, a nie na końcu alfabetu. Ustawienie bazy dziedziczą tylko tabele zakładane później bez własnego ustawienia.

    Typowe błędy

    Nazwa bazy musi brzmieć dokładnie kino - skrypty łączą się z bazą po nazwie, więc literówka zabiera też punkty za skrypty (R.5.1).

  2. Krok 2: Import danych z pliku kino.sql

    ok. 2 min
    Polecenie z arkusza

    Z rozpakowanego archiwum zaimportuj do utworzonej bazy dane z pliku kino.sql

    Zaznaczona baza kino, potem Import → kino.sql → Wykonaj. Powstają trzy tabele z ilustracji 1: aktorzy (10 aktorów, w polu plik_awatara nazwa pliku ze zdjęciem), filmy (15 filmów, czas_trwania w minutach) i filmy_aktorzy - same pary identyfikatorów, czyli informacja, kto grał w jakim filmie.

  3. Krok 3: Zrzut ekranu import.png

    Kryteria:

    R.1.1 Wykonany import do bazy danych kino - plik import.png

    ok. 2 min
    Polecenie z arkusza

    Wykonaj zrzut ekranu po imporcie. Zapisz zrzut w formacie PNG pod nazwą import. 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

    Print Screen, wklejenie do edytora grafiki i zapis jako import.png. Uwaga na formaty: import idzie do PNG, a zrzuty zapytań do JPEG.

    Typowe błędy

    Wykadrowany zrzut albo zrzut bez paska zadań nie jest oceniany (uwaga w kluczu przy R.1).

  4. Krok 4: Zapytanie 1: filmy trwające co najmniej 100 minut

    Kryteria: ,

    R.1.2 W pliku kwerendy.txt zapisane co najmniej jedno zapytanie SQL, wynikające z treści zadania

    R.1.3 Wykonane zapytanie 1 wybierające jedynie pola id_filmu, tytul, rok_produkcji, czas_trwania z tabeli filmy dla filmów, które trwają nie krócej niż 100 minut. W pliku z kwerendami lub na zrzucie istnieje zapis np.: SELECT id_filmu, tytul, rok_produkcji, czas_trwania FROM filmy WHERE czas_trwania >= 100; oraz na zrzucie jest dokładnie 11 rekordów

    ok. 2 min
    Polecenie z arkusza

    Zapytanie 1: wybierające jedynie identyfikator, tytuł, rok produkcji oraz czas trwania, dla filmów które trwają nie krócej niż 100 minut

    • SELECT id_filmu, tytul, rok_produkcji, czas_trwania - cztery pola, bez reżysera,
    • FROM filmy,
    • WHERE czas_trwania >= 100 - „nie krócej niż 100 minut” to większe lub równe, więc film „Nocne Opowieści” (dokładnie 100 minut) też jest w wyniku.

    Wynik: 11 wierszy, jak w kluczu. Zapytania trafiają do kwerendy.txt (wystarczy w nim jedno zapytanie, żeby był R.1.2, ale zapisuje się wszystkie), zrzut wyniku do kw1.jpg.

    Typowe błędy

    czas_trwania > 100 gubi film trwający równo 100 minut - wyjdzie 10 wierszy zamiast 11.

    kwerendy.txt Tekst nowy plik
    -- Zapytanie 1
    SELECT id_filmu, tytul, rok_produkcji, czas_trwania FROM filmy WHERE czas_trwania >= 100;
    Podgląd strony po tym kroku
    Podgląd strony po kroku 4
  5. Krok 5: Zapytanie 2: aktor o identyfikatorze 3

    Kryteria:

    R.1.4 Wykonane zapytanie 2 wybierające jedynie pola imie, nazwisko, plik_awatara z tabeli aktorzy dla aktora, którego identyfikator to 3. W pliku z kwerendami lub na zrzucie istnieje zapis np.: SELECT imie, nazwisko, plik_awatara FROM aktorzy WHERE id_aktora = 3; oraz na zrzucie jest dokładnie 1 wiersz przedstawiający dane: Jerzy, Pasek, awatar_3.jpg

    ok. 1 min
    Polecenie z arkusza

    Zapytanie 2: wybierające jedynie imię, nazwisko i nazwę pliku awatara aktora, którego identyfikator to 3

    • SELECT imie, nazwisko, plik_awatara - trzy pola,
    • FROM aktorzy,
    • WHERE id_aktora = 3 - klucz główny, więc wynik ma najwyżej jeden wiersz.

    Wynik: Jerzy Pasek, awatar_3.jpg. To zapytanie wróci w Skrypcie 2 - zamiast trójki stanie w nim identyfikator z adresu strony. Zrzut: kw2.jpg.

    kwerendy.txt Tekst zmienione: 3 linie
    -- Zapytanie 1
    SELECT id_filmu, tytul, rok_produkcji, czas_trwania FROM filmy WHERE czas_trwania >= 100;
    
    -- Zapytanie 2
    SELECT imie, nazwisko, plik_awatara FROM aktorzy WHERE id_aktora = 3;
    Podgląd strony po tym kroku
    Podgląd strony po kroku 5
  6. Krok 6: Zapytanie 3: aktorzy alfabetycznie

    Kryteria:

    R.1.5 Wykonane zapytanie 3 wybierające wszystkie dane o aktorach, sortując je według nazwiska i imienia alfabetycznie (rosnąco). W pliku z kwerendami lub na zrzucie istnieje zapis np.: SELECT * FROM aktorzy ORDER BY nazwisko, imie; (opcjonalnie ASC, zamiast * można wymienić wszystkie pola z tabeli) oraz na zrzucie jest co najmniej 10 rekordów

    ok. 1 min
    Polecenie z arkusza

    Zapytanie 3: wybierające wszystkie dane o aktorach, sortując je według nazwiska i imienia alfabetycznie (rosnąco)

    • SELECT * - wszystkie pola (Skrypt 1 potrzebuje identyfikatora, imienia, nazwiska i pliku awatara),
    • FROM aktorzy,
    • ORDER BY nazwisko, imie - najpierw po nazwisku, a przy takim samym nazwisku po imieniu; „rosnąco” to domyślny kierunek, ASC można dopisać.

    Wynik: 10 aktorów od Anaïs do Teixeiry - w tej samej kolejności co awatary na ilustracji 2. Zrzut: kw3.jpg.

    kwerendy.txt Tekst zmienione: 3 linie
    -- Zapytanie 1
    SELECT id_filmu, tytul, rok_produkcji, czas_trwania FROM filmy WHERE czas_trwania >= 100;
    
    -- Zapytanie 2
    SELECT imie, nazwisko, plik_awatara FROM aktorzy WHERE id_aktora = 3;
    
    -- Zapytanie 3
    SELECT * FROM aktorzy ORDER BY nazwisko, imie;
    Podgląd strony po tym kroku
    Podgląd strony po kroku 6
  7. Krok 7: Zapytanie 4: filmy aktora 3 przez relację

    Kryteria:

    R.1.6 Wykonane zapytanie 4 wybierające jedynie identyfikator, tytuł oraz rok produkcji filmów, w których gra aktor z identyfikatorem 3. W pliku z kwerendami lub na zrzucie istnieje zapis np.: SELECT filmy.id_filmu, tytul, rok_produkcji FROM filmy JOIN filmy_aktorzy USING(id_filmu) WHERE filmy_aktorzy.id_aktora = 3; (możliwe również porównanie kluczy po ON lub WHERE) oraz na zrzucie jest dokładnie 11 rekordów

    ok. 3 min
    Polecenie z arkusza

    Zapytanie 4: wybierające jedynie identyfikatory, tytuły oraz rok produkcji filmów, w których gra aktor z identyfikatorem 3. Należy posłużyć się relacją

    • SELECT filmy.id_filmu, tytul, rok_produkcji - pole id_filmu jest w obu tabelach, więc trzeba wskazać, z której (inaczej błąd „Column 'id_filmu' in field list is ambiguous”),
    • FROM filmy JOIN filmy_aktorzy - złączenie filmów z tabelą pośrednią,
    • ON filmy.id_filmu = filmy_aktorzy.id_filmu - warunek relacji z ilustracji 1 (klucz uznaje też USING(id_filmu) - sprawdzone, ten sam wynik),
    • WHERE filmy_aktorzy.id_aktora = 3 - tylko pary z aktorem 3.

    Wynik: 11 filmów, jak w kluczu. Z tego zapytania powstanie Skrypt 3. Zrzut: kw4.jpg.

    kwerendy.txt Tekst zmienione: 3 linie
    -- Zapytanie 1
    SELECT id_filmu, tytul, rok_produkcji, czas_trwania FROM filmy WHERE czas_trwania >= 100;
    
    -- Zapytanie 2
    SELECT imie, nazwisko, plik_awatara FROM aktorzy WHERE id_aktora = 3;
    
    -- Zapytanie 3
    SELECT * FROM aktorzy ORDER BY nazwisko, imie;
    
    -- Zapytanie 4
    SELECT filmy.id_filmu, tytul, rok_produkcji FROM filmy JOIN filmy_aktorzy ON filmy.id_filmu = filmy_aktorzy.id_filmu WHERE filmy_aktorzy.id_aktora = 3;
    Podgląd strony po tym kroku
    Podgląd strony po kroku 7
  8. Krok 8: Zapytanie 5: liczba filmów każdego aktora

    Kryteria:

    R.1.7 Wykonane zapytanie 5 wybierające id aktora oraz zliczające liczbę filmów alias liczba_filmow, w których grał każdy aktor, pogrupowane ze względu na identyfikator aktora. W pliku z kwerendami lub na zrzucie istnieje zapis np.: SELECT id_aktora, COUNT(*) AS liczba_filmow FROM filmy_aktorzy GROUP BY id_aktora; (AS opcjonalnie, zamiast * możliwe dowolne pole) oraz na zrzucie jest dokładnie 9 rekordów: 1, 8; 2, 9; 3, 11; 4, 10; 5, 9; 6, 8; 7, 11; 9, 11; 10, 7

    ok. 2 min
    Polecenie z arkusza

    Zapytanie 5: wybierające id aktora oraz zliczające liczbę filmów, alias „liczba_filmow”, w których grał każdy aktor, pogrupowane ze względu na identyfikator aktora

    • SELECT id_aktora, COUNT(*) AS liczba_filmow - identyfikator i liczba wierszy w grupie pod nazwą z arkusza,
    • FROM filmy_aktorzy - wystarczy tabela pośrednia, bo każdy jej wiersz to jeden film aktora,
    • GROUP BY id_aktora - wiersze tego samego aktora zlewają się w jeden.

    Wynik: 9 wierszy (1, 8; 2, 9; 3, 11; 4, 10; 5, 9; 6, 8; 7, 11; 9, 11; 10, 7) - zgodnie z kluczem. Aktora 8 nie ma, bo nie ma go w żadnej parze; to Lorenzo Di Romano, dla którego Skrypt 3 wypisze, że nie gra w żadnej znanej produkcji. Zrzut: kw5.jpg.

    kwerendy.txt Tekst zmienione: 3 linie
    -- Zapytanie 1
    SELECT id_filmu, tytul, rok_produkcji, czas_trwania FROM filmy WHERE czas_trwania >= 100;
    
    -- Zapytanie 2
    SELECT imie, nazwisko, plik_awatara FROM aktorzy WHERE id_aktora = 3;
    
    -- Zapytanie 3
    SELECT * FROM aktorzy ORDER BY nazwisko, imie;
    
    -- Zapytanie 4
    SELECT filmy.id_filmu, tytul, rok_produkcji FROM filmy JOIN filmy_aktorzy ON filmy.id_filmu = filmy_aktorzy.id_filmu WHERE filmy_aktorzy.id_aktora = 3;
    
    -- Zapytanie 5
    SELECT id_aktora, COUNT(*) AS liczba_filmow FROM filmy_aktorzy GROUP BY id_aktora;
    Podgląd strony po tym kroku
    Podgląd strony po kroku 8
  9. Etap 2: Strona HTML

    Kroki 9-20 · po tym etapie masz 17 z 39 kryteriów (pkt)

    Krok 9: Plik index.php w HTML5 i awatary w folderze

    ok. 2 min
    Polecenie z arkusza

    Zapisane w języku HTML5

    Deklaracja <!DOCTYPE html> i szkielet strony. Rozszerzenie .php, bo dojdą skrypty; na egzaminie folder leży w htdocs XAMPP-a i strona otwiera się przez http://localhost/.... Do tego samego folderu trafiają pliki awatarów z katalogu img archiwum (awatar_1.jpg - awatar_10.jpg) - baza podaje samą nazwę pliku, więc obraz musi leżeć obok strony.

    index.php PHP nowy plik
    <!DOCTYPE html>
    <html>
    <head>
    </head>
    <body>
    </body>
    </html>
    Podgląd strony po tym kroku (index.php)
  10. Krok 10: Język strony

    Kryteria:

    R.2.1 W plikach index.php lub aktor.php znajduje się deklaracja HTML5 <!DOCTYPE HTML> i deklaracja języka zawartości witryny: polski np. <html lang="pl">

    ok. 1 min
    Polecenie z arkusza

    Zadeklarowany polski język zawartości witryny

    Atrybut lang="pl" w znaczniku <html> - razem z deklaracją HTML5 to jedno kryterium klucza.

    index.php PHP zmienione: 1 linia
    <!DOCTYPE html>
    <html lang="pl">
    <head>
    </head>
    <body>
    </body>
    </html>
    Podgląd strony po tym kroku (index.php)
  11. Krok 11: Kodowanie polskich znaków

    ok. 1 min
    Polecenie z arkusza

    Jawnie zastosowany właściwy standard kodowania polskich znaków

    <meta charset="UTF-8"> jako pierwszy element <head> - bez niego „Sobiesław” i „Élodie” mogą wyświetlić się krzakami.

    index.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 (index.php)
  12. Krok 12: Podpięcie arkusza stylów

    Kryteria:

    R.3.2 Strona zawiera działające połączenie z zewnętrznym arkuszem stylów o nazwie styl.css formatowanie CSS pochodzi jedynie z tego arkusza

    ok. 1 min
    Polecenie z arkusza

    Arkusz stylów w pliku o nazwie styl.css właściwie połączony z kodem strony

    Nazwa pliku: styl.css (nie style.css). Całe formatowanie ma pochodzić z tego pliku - żadnych atrybutów style w HTML-u ani w tekstach wypisywanych przez PHP.

    index.php PHP zmienione: 1 linia
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
    </body>
    </html>
    Podgląd strony po tym kroku (index.php)
  13. Krok 13: Bloki: dwa nagłówkowe, główny, stopka

    Kryteria:

    R.2.3 W sekcji body zdefiniowany jest podział na bloki za pomocą semantycznych znaczników HTML5: header+header, main, footer (dopuszcza się zastosowanie bloków pomocniczych)

    ok. 2 min
    Polecenie z arkusza

    Podział strony na bloki zrealizowany za pomocą semantycznych znaczników bloków języka HTML5 tak, aby po uruchomieniu w przeglądarce układ bloków na stronie był zgodny z ilustracją 3

    Klucz wymaga wprost header + header, main i footer (R.2.3). Oba bloki nagłówkowe to znaczniki <header>, więc dostają identyfikatory - logo i motto - po których CSS nada im różne szerokości. Obok siebie postawi je arkusz stylów.

    index.php PHP zmienione: 8 linii
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <header id="logo">
        </header>
        <header id="motto">
        </header>
        <main>
        </main>
        <footer>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (index.php)
  14. Krok 14: Blok nagłówkowy 1: nagłówek z odnośnikiem

    Kryteria:

    R.3.3 Blok nagłówkowy 1 zawiera odnośnik prowadzący do pliku index.php

    ok. 1 min
    Polecenie z arkusza

    Zawartość bloku nagłówkowego 1: nagłówek drugiego stopnia zawierający odnośnik do pliku index.php o treści „KinoTEKA”

    „Nagłówek zawierający odnośnik” - więc <a> stoi wewnątrz <h2>, nie odwrotnie. Na stronie aktor.php ten odnośnik będzie powrotem do listy aktorów.

    index.php PHP zmienione: 1 linia
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <header id="logo">
            <h2><a href="index.php">KinoTEKA</a></h2>
        </header>
        <header id="motto">
        </header>
        <main>
        </main>
        <footer>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (index.php)
  15. Krok 15: Blok nagłówkowy 2: paragraf z tekstem uwypuklonym

    Kryteria:

    R.2.5 W bloku nagłówkowym 1 umieszczony <h2> „KinoTEKA” oraz w bloku nagłówkowym 2 - <p> o treści „W naszej bazie znajdują się najlepsi aktorzy”

    ok. 1 min
    Polecenie z arkusza

    Zawartość bloku nagłówkowego 2: paragraf o treści „W naszej bazie znajdują się najlepsi aktorzy”. Tekst ten jest zapisany w znaczniku semantycznym oznaczającym tekst uwypuklony, formatowany domyślnie jako pochylony

    Tekst uwypuklony to <em> (emfaza) - przeglądarka domyślnie go pochyla. <i> też pochyla, ale nie jest znacznikiem semantycznym, o który prosi arkusz. Z nagłówkiem „KinoTEKA” z poprzedniego kroku to kryterium R.2.5.

    index.php PHP zmienione: 1 linia
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <header id="logo">
            <h2><a href="index.php">KinoTEKA</a></h2>
        </header>
        <header id="motto">
            <p><em>W naszej bazie znajdują się najlepsi aktorzy</em></p>
        </header>
        <main>
        </main>
        <footer>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (index.php)
  16. Krok 16: Stopka: autor w znaczniku tekstu ważnego

    Kryteria: ,

    R.2.6 W stopce umieszczony <p> o treści: "Autor:" z numerem zdającego

    R.2.7 W bloku nagłówkowym 2 użyty znacznik semantyczny <em> do tekstu oraz w stopce użyty znacznik semantyczny <strong> do numeru zdającego

    ok. 1 min
    Polecenie z arkusza

    Zawartość stopki: paragraf o treści „Autor: ”, dalej wstawiony numer zdającego. Numer zdającego jest zapisany w znaczniku semantycznym oznaczającym tekst ważny, formatowany domyślnie jako pogrubiony

    Tekst ważny to <strong> - domyślnie pogrubiony (<b> też pogrubia, ale nie niesie znaczenia). Na egzaminie w miejscu imienia i nazwiska wpisuje się numer zdającego, czyli PESEL; w tym rozwiązaniu stoi tam „Bartosz Bryniarski”. Razem z <em> z bloku nagłówkowego 2 to kryterium R.2.7.

    index.php PHP zmienione: 1 linia
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <header id="logo">
            <h2><a href="index.php">KinoTEKA</a></h2>
        </header>
        <header id="motto">
            <p><em>W naszej bazie znajdują się najlepsi aktorzy</em></p>
        </header>
        <main>
        </main>
        <footer>
            <p>Autor: <strong>Bartosz Bryniarski</strong></p>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (index.php)
  17. Krok 17: index.php: tytuł strony

    Kryteria:

    R.2.2 W sekcji head znajduje się jawnie podany standard kodowania polskich znaków. Stronie index.php nadano tytuł "Lista aktorów | KinoTEKA " lub stronie aktor.php nadano tytuł "Informacje o aktorze | KinoTEKA"

    ok. 1 min
    Polecenie z arkusza

    Tytuł strony widoczny na karcie przeglądarki: „Lista aktorów | KinoTEKA”

    <title> w <head> - z pionową kreską i spacjami, jak w arkuszu. Z kodowaniem znaków to jedno kryterium klucza (R.2.2).

    index.php PHP zmienione: 1 linia
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <title>Lista aktorów | KinoTEKA</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <header id="logo">
            <h2><a href="index.php">KinoTEKA</a></h2>
        </header>
        <header id="motto">
            <p><em>W naszej bazie znajdują się najlepsi aktorzy</em></p>
        </header>
        <main>
        </main>
        <footer>
            <p>Autor: <strong>Bartosz Bryniarski</strong></p>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (index.php)
  18. Krok 18: index.php: nagłówek pierwszego stopnia

    Kryteria:

    R.2.4 W bloku głównym na stronie głównej umieszczony <h1> o treści: „Najlepsi aktorzy tylko w naszym kinie”

    ok. 1 min
    Polecenie z arkusza

    Nagłówek pierwszego stopnia o treści: „Najlepsi aktorzy tylko w naszym kinie”

    <h1> na początku bloku głównego. Strona ma <h2> w nagłówku przed <h1> - arkusz tak ustawia stopnie i nie ma w tym błędu.

    index.php PHP zmienione: 1 linia
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <title>Lista aktorów | KinoTEKA</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <header id="logo">
            <h2><a href="index.php">KinoTEKA</a></h2>
        </header>
        <header id="motto">
            <p><em>W naszej bazie znajdują się najlepsi aktorzy</em></p>
        </header>
        <main>
            <h1>Najlepsi aktorzy tylko w naszym kinie</h1>
        </main>
        <footer>
            <p>Autor: <strong>Bartosz Bryniarski</strong></p>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (index.php)
  19. Krok 19: index.php: blok wszystkich aktorów

    Kryteria:

    R.2.8 Na stronie głównej w bloku głównym utworzony blok wszystkich aktorów (w HTML lub skrypcie)

    ok. 1 min
    Polecenie z arkusza

    Blok wszystkich aktorów wypełniony skryptem 1

    Pusty <div id="actors"> pod nagłówkiem - Skrypt 1 wypisze w nim po jednym bloku na aktora. Zwykły div, bo to tylko pojemnik do ułożenia bloków, bez własnego znaczenia; identyfikator actors przyda się w CSS.

    index.php PHP zmienione: 2 linie
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <title>Lista aktorów | KinoTEKA</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <header id="logo">
            <h2><a href="index.php">KinoTEKA</a></h2>
        </header>
        <header id="motto">
            <p><em>W naszej bazie znajdują się najlepsi aktorzy</em></p>
        </header>
        <main>
            <h1>Najlepsi aktorzy tylko w naszym kinie</h1>
            <div id="actors">
            </div>
        </main>
        <footer>
            <p>Autor: <strong>Bartosz Bryniarski</strong></p>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (index.php)
  20. Krok 20: aktor.php: kopia strony z innym tytułem

    ok. 2 min
    Polecenie z arkusza

    Tytuł strony widoczny na karcie przeglądarki: „Informacje o aktorze | KinoTEKA”

    Obie strony mają wspólne bloki nagłówkowe, stopkę, kodowanie i arkusz stylów, więc aktor.php powstaje jako kopia index.php. Zmienia się tytuł, a z bloku głównego znika <h1> - na tej stronie nagłówkiem pierwszego stopnia będzie imię i nazwisko aktora wypisane przez Skrypt 2. Blok wszystkich aktorów zostaje: arkusz każe wypełnić go Skryptem 2, a pod nim stanie efekt Skryptu 3.

    aktor.php PHP nowy plik
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <title>Informacje o aktorze | KinoTEKA</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <header id="logo">
            <h2><a href="index.php">KinoTEKA</a></h2>
        </header>
        <header id="motto">
            <p><em>W naszej bazie znajdują się najlepsi aktorzy</em></p>
        </header>
        <main>
            <div id="actors">
            </div>
        </main>
        <footer>
            <p>Autor: <strong>Bartosz Bryniarski</strong></p>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (aktor.php)
  21. Etap 3: Styl CSS

    Kroki 21-32 · po tym etapie masz 28 z 39 kryteriów (pkt)

    Krok 21: Krój czcionki dla wszystkich elementów

    Kryteria:

    R.4.1 domyślnie dla wszystkich selektorów (*): krój czcionki "Gill Sans MT", "Calibri" (dozwolona tylko taka kolejność)

    ok. 1 min
    Polecenie z arkusza

    Domyślne formatowanie wszystkich selektorów: krój czcionki „Gill Sans MT”, a w przypadku jej braku „Calibri”

    Selektor uniwersalny *. Nazwa kroju ze spacjami musi być w cudzysłowie; kolejność na liście to kolejność prób - najpierw „Gill Sans MT”, a gdy go nie ma, Calibri (klucz dopuszcza tylko taką kolejność).

    styl.css CSS nowy plik
    * {
        font-family: "Gill Sans MT", Calibri;
    }
    Podgląd strony po tym kroku (index.php)
  22. Krok 22: Ciało strony: szerokość i wyśrodkowanie

    Kryteria:

    R.4.3 dla ciała strony lub dla bloku wszystkich aktorów - marginesy zewnętrzne górny i dolny 0, lewy i prawy auto

    ok. 1 min
    Polecenie z arkusza

    Dla selektora ciała strony: szerokość 90%, marginesy zewnętrzne górny i dolny 0, lewy i prawy automatycznie wyliczone przez przeglądarkę

    Skrót margin: 0 auto - pierwsza wartość to górny i dolny margines, druga lewy i prawy. auto po bokach rozdziela wolne miejsce po równo, więc strona szeroka na 90% okna staje na środku. Zgodnie z uwagą arkusza selektor to sam znacznik body.

    styl.css CSS zmienione: 4 linie
    * {
        font-family: "Gill Sans MT", Calibri;
    }
    body {
        width: 90%;
        margin: 0 auto;
    }
    Podgląd strony po tym kroku (index.php)
  23. Krok 23: Blok nagłówkowy 1: szerokość

    ok. 1 min
    Polecenie z arkusza

    Dla bloku nagłówkowego 1: szerokość 40%

    Selektor identyfikatora #logo. Bloki jeszcze stoją jeden pod drugim - obok siebie postawi je krok z układem.

    styl.css CSS zmienione: 3 linie
    * {
        font-family: "Gill Sans MT", Calibri;
    }
    body {
        width: 90%;
        margin: 0 auto;
    }
    #logo {
        width: 40%;
    }
    Podgląd strony po tym kroku (index.php)
  24. Krok 24: Blok nagłówkowy 2: szerokość i tekst do prawej

    Kryteria:

    R.4.6 wyrównanie tekstu do prawej strony dla bloku nagłówkowego 2

    ok. 1 min
    Polecenie z arkusza

    Dla bloku nagłówkowego 2: szerokość 60% oraz wyrównanie tekstu do prawej strony

    40% + 60% = cała szerokość strony, więc oba bloki zmieszczą się w jednym rzędzie. text-align: right dosuwa motto do prawej krawędzi, jak na ilustracji 2.

    styl.css CSS zmienione: 4 linie
    * {
        font-family: "Gill Sans MT", Calibri;
    }
    body {
        width: 90%;
        margin: 0 auto;
    }
    #logo {
        width: 40%;
    }
    #motto {
        width: 60%;
        text-align: right;
    }
    Podgląd strony po tym kroku (index.php)
  25. Krok 25: Układ bloków zgodny z ilustracją 3

    Kryteria:

    R.3.1 Układ bloków po uruchomieniu strony w przeglądarce jest zgodny z ilustracją 3 w arkuszu egzaminacyjnym (prawidłowo zastosowano właściwości CSS decydujące o układzie bloków na stronie, np. float i clear albo display flex albo grid albo position), (nie należy brać pod uwagę bloków aktorów)

    ok. 2 min
    Polecenie z arkusza

    Podział strony na bloki zrealizowany za pomocą semantycznych znaczników bloków języka HTML5 tak, aby po uruchomieniu w przeglądarce układ bloków na stronie był zgodny z ilustracją 3

    Arkusz nie mówi, jak ułożyć bloki. Najprościej: oba bloki nagłówkowe float: left - pierwszy staje przy lewej krawędzi, drugi tuż obok (szerokości sumują się do 100%). Blok główny dostaje clear: both: bez tego wjechałby w wolne miejsce obok pływających nagłówków, a ma zacząć się dopiero pod nimi. Stopka idzie za blokiem głównym sama.

    styl.css CSS zmienione: 6 linii
    * {
        font-family: "Gill Sans MT", Calibri;
    }
    body {
        width: 90%;
        margin: 0 auto;
    }
    #logo {
        width: 40%;
    }
    #motto {
        width: 60%;
        text-align: right;
    }
    #logo, #motto {
        float: left;
    }
    main {
        clear: both;
    }
    Podgląd strony po tym kroku (index.php)
  26. Krok 26: Blok wszystkich aktorów: marginesy

    ok. 1 min
    Polecenie z arkusza

    Dla bloku wszystkich aktorów: marginesy zewnętrzne górny i dolny 0, lewy i prawy automatyczne

    To samo margin: 0 auto co dla body. Blok nie ma ustawionej szerokości, więc zajmuje całą szerokość strony i marginesy boczne wychodzą zerowe - ale reguła jest zgodna z arkuszem i zadziała, gdy blok kiedyś dostanie szerokość.

    styl.css CSS zmienione: 3 linie
    * {
        font-family: "Gill Sans MT", Calibri;
    }
    body {
        width: 90%;
        margin: 0 auto;
    }
    #logo {
        width: 40%;
    }
    #motto {
        width: 60%;
        text-align: right;
    }
    #logo, #motto {
        float: left;
    }
    main {
        clear: both;
    }
    #actors {
        margin: 0 auto;
    }
    Podgląd strony po tym kroku (index.php)
  27. Krok 27: index.php: blok pojedynczego aktora obok siebie

    Kryteria: ,

    R.4.4 dla bloku pojedynczego aktora - tekst wyśrodkowany

    R.4.5 bloki pojedynczych aktorów na stronie głównej są ustawione obok siebie (np. float, flex, grid)

    ok. 2 min
    Polecenie z arkusza

    Dla bloku pojedynczego aktora na stronie index.php, generowanego skryptem 1: szerokość 15 em, tekst wyśrodkowany, bloki są wyświetlane obok siebie

    Bloki aktorów wypisze Skrypt 1 z klasą actor - klasa, bo bloków jest dziesięć. display: inline-block układa je jak wyrazy w linii: obok siebie, a gdy brak miejsca, w następnym rzędzie (na ilustracji 2 sześć w pierwszym rzędzie, cztery w drugim). Jednostka em to wielokrotność rozmiaru czcionki - 15em to około 240 px. Efekt będzie widać, gdy Skrypt 1 wypisze bloki.

    styl.css CSS zmienione: 5 linii
    * {
        font-family: "Gill Sans MT", Calibri;
    }
    body {
        width: 90%;
        margin: 0 auto;
    }
    #logo {
        width: 40%;
    }
    #motto {
        width: 60%;
        text-align: right;
    }
    #logo, #motto {
        float: left;
    }
    main {
        clear: both;
    }
    #actors {
        margin: 0 auto;
    }
    .actor {
        width: 15em;
        text-align: center;
        display: inline-block;
    }
    Podgląd strony po tym kroku (index.php)
  28. Krok 28: aktor.php: blok pojedynczego aktora

    ok. 1 min
    Polecenie z arkusza

    Dla bloku pojedynczego aktora na stronie aktor.php, generowanego skryptem 2: szerokość 25 em, tekst wyśrodkowany

    Na aktor.php blok aktora jest jeden i większy, więc dostaje inną klasę - actor-profile - z szerokością 25em i bez inline-block.

    styl.css CSS zmienione: 4 linie
    * {
        font-family: "Gill Sans MT", Calibri;
    }
    body {
        width: 90%;
        margin: 0 auto;
    }
    #logo {
        width: 40%;
    }
    #motto {
        width: 60%;
        text-align: right;
    }
    #logo, #motto {
        float: left;
    }
    main {
        clear: both;
    }
    #actors {
        margin: 0 auto;
    }
    .actor {
        width: 15em;
        text-align: center;
        display: inline-block;
    }
    .actor-profile {
        width: 25em;
        text-align: center;
    }
    Podgląd strony po tym kroku (index.php)
  29. Krok 29: Obraz: szerokość i zaokrąglenie w koło

    Kryteria: ,

    R.4.2 szerokości elementów: 90% - dla selektora body, 40% - dla bloku nagłówkowego 1 60% - dla bloku nagłówkowego 2 15em - dla bloku pojedynczego aktora na stronie index.php 25em - dla bloku pojedynczego aktora na stronie aktor.php 90% - dla selektora img Wystarczą 4 z 6 ustawień

    R.4.8 dla obrazu - zaokrąglenie obramowania 50%

    ok. 1 min
    Polecenie z arkusza

    Dla selektora obrazu: szerokość 90%, zaokrąglenie obramowania 50%

    Szerokość 90% liczy się od bloku aktora, więc awatar na index.php jest mniejszy niż na aktor.php. border-radius: 50% zaokrągla każdy róg o połowę boku - kwadratowe zdjęcia z archiwum (od 500 × 500 do 1100 × 1100 pikseli) stają się kołami. Tym krokiem są już ustawione wszystkie szerokości z arkusza (klucz wymaga 4 z 6).

    styl.css CSS zmienione: 4 linie
    * {
        font-family: "Gill Sans MT", Calibri;
    }
    body {
        width: 90%;
        margin: 0 auto;
    }
    #logo {
        width: 40%;
    }
    #motto {
        width: 60%;
        text-align: right;
    }
    #logo, #motto {
        float: left;
    }
    main {
        clear: both;
    }
    #actors {
        margin: 0 auto;
    }
    .actor {
        width: 15em;
        text-align: center;
        display: inline-block;
    }
    .actor-profile {
        width: 25em;
        text-align: center;
    }
    img {
        width: 90%;
        border-radius: 50%;
    }
    Podgląd strony po tym kroku (index.php)
  30. Krok 30: Paragraf w bloku aktora: większa czcionka

    Kryteria:

    R.4.7 dla selektora p znajdującego się wyłącznie w bloku pojedynczego aktora - rozmiar czcionki 125%

    ok. 1 min
    Polecenie z arkusza

    Dla selektora paragrafu znajdującego się w bloku pojedynczego aktora: rozmiar czcionki 125%

    Selektor potomka .actor p - działa tylko na paragrafy wewnątrz bloku aktora. Samo p powiększyłoby też motto, stopkę i napis Skryptu 3 (na ilustracji 4 ten napis jest mały). To nadal selektor znacznika p, jak wymaga uwaga arkusza.

    styl.css CSS zmienione: 3 linie
    * {
        font-family: "Gill Sans MT", Calibri;
    }
    body {
        width: 90%;
        margin: 0 auto;
    }
    #logo {
        width: 40%;
    }
    #motto {
        width: 60%;
        text-align: right;
    }
    #logo, #motto {
        float: left;
    }
    main {
        clear: both;
    }
    #actors {
        margin: 0 auto;
    }
    .actor {
        width: 15em;
        text-align: center;
        display: inline-block;
    }
    .actor-profile {
        width: 25em;
        text-align: center;
    }
    img {
        width: 90%;
        border-radius: 50%;
    }
    .actor p {
        font-size: 125%;
    }
    Podgląd strony po tym kroku (index.php)
  31. Krok 31: Odnośniki: czarne, bez podkreślenia

    Kryteria:

    R.4.9 dla selektora a - czarny kolor czcionki i brak podkreślenia

    ok. 1 min
    Polecenie z arkusza

    Dla selektora odnośnika: kolor czcionki czarny, brak podkreślenia

    text-decoration: none zdejmuje podkreślenie. Bloki aktorów są odnośnikami, więc bez tej reguły imiona pod awatarami byłyby niebieskie i podkreślone.

    styl.css CSS zmienione: 4 linie
    * {
        font-family: "Gill Sans MT", Calibri;
    }
    body {
        width: 90%;
        margin: 0 auto;
    }
    #logo {
        width: 40%;
    }
    #motto {
        width: 60%;
        text-align: right;
    }
    #logo, #motto {
        float: left;
    }
    main {
        clear: both;
    }
    #actors {
        margin: 0 auto;
    }
    .actor {
        width: 15em;
        text-align: center;
        display: inline-block;
    }
    .actor-profile {
        width: 25em;
        text-align: center;
    }
    img {
        width: 90%;
        border-radius: 50%;
    }
    .actor p {
        font-size: 125%;
    }
    a {
        color: black;
        text-decoration: none;
    }
    Podgląd strony po tym kroku (index.php)
  32. Krok 32: Odnośnik pod kursorem

    Kryteria:

    R.4.10 gdy kursor znajdzie się na odnośniku, jego kolor czcionki zmienia się na #E30613

    ok. 1 min
    Polecenie z arkusza

    Gdy kursor znajdzie się na odnośniku: kolor czcionki #E30613

    Pseudoklasa :hover. Na ilustracji 2 kursor stoi na drugim awatarze - dlatego „Davide Costaluca” jest czerwony.

    styl.css CSS zmienione: 3 linie
    * {
        font-family: "Gill Sans MT", Calibri;
    }
    body {
        width: 90%;
        margin: 0 auto;
    }
    #logo {
        width: 40%;
    }
    #motto {
        width: 60%;
        text-align: right;
    }
    #logo, #motto {
        float: left;
    }
    main {
        clear: both;
    }
    #actors {
        margin: 0 auto;
    }
    .actor {
        width: 15em;
        text-align: center;
        display: inline-block;
    }
    .actor-profile {
        width: 25em;
        text-align: center;
    }
    img {
        width: 90%;
        border-radius: 50%;
    }
    .actor p {
        font-size: 125%;
    }
    a {
        color: black;
        text-decoration: none;
    }
    a:hover {
        color: #E30613;
    }
    Podgląd strony po tym kroku (index.php)
  33. Etap 4: Skrypty PHP

    Kroki 33-43 · po tym etapie masz 39 z 39 kryteriów (pkt)

    Krok 33: index.php: połączenie z bazą i zamknięcie

    Kryteria:

    R.5.1 Dowolny ze skryptów realizuje połączenie z serwerem bazy danych i wybór bazy kino , a ostatnią operacją na bazie jest jej zamknięcie

    ok. 2 min
    Polecenie z arkusza

    Łączą się z serwerem bazodanowym na localhost, użytkownik root bez hasła, baza danych o nazwie kino. Na końcu skrypt zamyka połączenie z bazą

    Skrypt 1 stoi wewnątrz bloku wszystkich aktorów - to, co wypisze, znajdzie się w środku <div id="actors">. mysqli_connect z czterema argumentami łączy się z serwerem i od razu wybiera bazę; uchwyt w zmiennej $connection. Druga linia już teraz zamyka połączenie - kolejne instrukcje będą dopisywane nad nią. Od tego kroku podgląd to wynik prawdziwego uruchomienia strony.

    index.php PHP zmienione: 4 linie
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <title>Lista aktorów | KinoTEKA</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <header id="logo">
            <h2><a href="index.php">KinoTEKA</a></h2>
        </header>
        <header id="motto">
            <p><em>W naszej bazie znajdują się najlepsi aktorzy</em></p>
        </header>
        <main>
            <h1>Najlepsi aktorzy tylko w naszym kinie</h1>
            <div id="actors">
                <?php
                    $connection = mysqli_connect("localhost", "root", "", "kino");
                    mysqli_close($connection);
                ?>
            </div>
        </main>
        <footer>
            <p>Autor: <strong>Bartosz Bryniarski</strong></p>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (index.php)
  34. Krok 34: Skrypt 1: zapytanie 3

    Kryteria:

    R.5.2 Skrypt 1 (strona główna) zawiera instrukcję wysyłającą do bazy zapytanie 3

    ok. 1 min
    Polecenie z arkusza

    Wysyła do bazy danych zapytanie 3

    Zapytanie 3 bez zmian, w zmiennej $query. mysqli_query wysyła je do bazy, a w $result zostaje wynik do odczytania wiersz po wierszu. Strona jeszcze niczego nie wypisuje.

    index.php PHP zmienione: 2 linie
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <title>Lista aktorów | KinoTEKA</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <header id="logo">
            <h2><a href="index.php">KinoTEKA</a></h2>
        </header>
        <header id="motto">
            <p><em>W naszej bazie znajdują się najlepsi aktorzy</em></p>
        </header>
        <main>
            <h1>Najlepsi aktorzy tylko w naszym kinie</h1>
            <div id="actors">
                <?php
                    $connection = mysqli_connect("localhost", "root", "", "kino");
                    $query = "SELECT * FROM aktorzy ORDER BY nazwisko, imie;";
                    $result = mysqli_query($connection, $query);
                    mysqli_close($connection);
                ?>
            </div>
        </main>
        <footer>
            <p>Autor: <strong>Bartosz Bryniarski</strong></p>
        </footer>
    </body>
    </html>

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

  35. Krok 35: Skrypt 1: blok aktora z imieniem i nazwiskiem

    ok. 3 min
    Polecenie z arkusza

    Dla każdego wiersza zwróconego z bazy tworzy blok pojedynczego aktora zawierający paragraf zawierający tekst „<IMIE> <NAZWISKO>”

    mysqli_fetch_row oddaje kolejny wiersz jako tablicę numerowaną od zera w kolejności kolumn tabeli: $row[0] - id, $row[1] - imię, $row[2] - nazwisko, $row[3] - ocena, $row[4] - plik awatara. Po ostatnim wierszu zwraca null i pętla while się kończy. Na razie każdy blok actor ma tylko paragraf - widać dziesięć nazwisk w kolejności zapytania 3, już obok siebie dzięki inline-block. Cudzysłowy w HTML-u wewnątrz napisu PHP poprzedza ukośnik \".

    index.php PHP zmienione: 5 linii
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <title>Lista aktorów | KinoTEKA</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <header id="logo">
            <h2><a href="index.php">KinoTEKA</a></h2>
        </header>
        <header id="motto">
            <p><em>W naszej bazie znajdują się najlepsi aktorzy</em></p>
        </header>
        <main>
            <h1>Najlepsi aktorzy tylko w naszym kinie</h1>
            <div id="actors">
                <?php
                    $connection = mysqli_connect("localhost", "root", "", "kino");
                    $query = "SELECT * FROM aktorzy ORDER BY nazwisko, imie;";
                    $result = mysqli_query($connection, $query);
                    while ($row = mysqli_fetch_row($result)) {
                        echo "<div class=\"actor\">";
                        echo "<p>$row[1] $row[2]</p>";
                        echo "</div>";
                    }
                    mysqli_close($connection);
                ?>
            </div>
        </main>
        <footer>
            <p>Autor: <strong>Bartosz Bryniarski</strong></p>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (index.php)
  36. Krok 36: Skrypt 1: awatar z tekstem alternatywnym i atrybutem title

    Kryteria: , ,

    R.5.3 Skrypt 1 wyświetla obrazy oraz imię i nazwisko aktorów dla wszystkich zwróconych zapytaniem wierszy

    R.3.5 Na stronie głównej obrazy znajdujące się w blokach pojedynczych aktorów mają ustawiony tekst alternatywny i atrybut title

    R.2.9 Na stronie głównej w bloku wszystkich aktorów znajduje się co najmniej jeden blok pojedynczego aktora zawierający obraz oraz paragraf (w HTML lub skrypcie)

    ok. 3 min
    Polecenie z arkusza

    Obraz, którego źródłem jest plik podany w kolumnie plik_awatara, z tekstem alternatywnym oraz atrybutem title z wartością „<IMIE> <NAZWISKO>” (Ilustracja 2, awatar 2)

    Źródło obrazu to piąta kolumna, $row[4] - sama nazwa pliku, dlatego awatary leżą obok strony. Ten sam tekst trafia do alt (czyta go czytnik ekranu i widać go, gdy obraz się nie wczyta) i do title - to dymek, który pokazuje się po najechaniu kursorem, jak przy drugim awatarze na ilustracji 2. Podgląd wygląda już jak ilustracja 2: dziesięć okrągłych awatarów z podpisami.

    index.php PHP zmienione: 1 linia
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <title>Lista aktorów | KinoTEKA</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <header id="logo">
            <h2><a href="index.php">KinoTEKA</a></h2>
        </header>
        <header id="motto">
            <p><em>W naszej bazie znajdują się najlepsi aktorzy</em></p>
        </header>
        <main>
            <h1>Najlepsi aktorzy tylko w naszym kinie</h1>
            <div id="actors">
                <?php
                    $connection = mysqli_connect("localhost", "root", "", "kino");
                    $query = "SELECT * FROM aktorzy ORDER BY nazwisko, imie;";
                    $result = mysqli_query($connection, $query);
                    while ($row = mysqli_fetch_row($result)) {
                        echo "<div class=\"actor\">";
                        echo "<img src=\"$row[4]\" alt=\"$row[1] $row[2]\" title=\"$row[1] $row[2]\">";
                        echo "<p>$row[1] $row[2]</p>";
                        echo "</div>";
                    }
                    mysqli_close($connection);
                ?>
            </div>
        </main>
        <footer>
            <p>Autor: <strong>Bartosz Bryniarski</strong></p>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (index.php)
  37. Krok 37: Skrypt 1: blok aktora jako odnośnik do aktor.php

    Kryteria:

    R.3.4 Na stronie głównej po kliknięciu bloku pojedynczego aktora jest otwierana strona aktor.php?id=… , gdzie … to id wybranego aktora (wystarczy sprawdzić dla dwóch bloków)

    ok. 2 min
    Polecenie z arkusza

    Wygenerowany blok pojedynczego aktora jest odnośnikiem do pliku aktor.php?id=<ID_AKTORA>

    Cały blok (obraz i paragraf) trafia do środka <a> - kliknięcie w awatar albo w nazwisko otwiera aktor.php. Za znakiem zapytania stoi parametr id z identyfikatorem z bazy ($row[0]), np. aktor.php?id=7 dla Davide Costaluki - to właśnie odczyta aktor.php z tablicy $_GET. W HTML5 odnośnik może obejmować element blokowy. Teraz działa też reguła a: podpisy są czarne, a pod kursorem czerwone.

    index.php PHP zmienione: 2 linie
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <title>Lista aktorów | KinoTEKA</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <header id="logo">
            <h2><a href="index.php">KinoTEKA</a></h2>
        </header>
        <header id="motto">
            <p><em>W naszej bazie znajdują się najlepsi aktorzy</em></p>
        </header>
        <main>
            <h1>Najlepsi aktorzy tylko w naszym kinie</h1>
            <div id="actors">
                <?php
                    $connection = mysqli_connect("localhost", "root", "", "kino");
                    $query = "SELECT * FROM aktorzy ORDER BY nazwisko, imie;";
                    $result = mysqli_query($connection, $query);
                    while ($row = mysqli_fetch_row($result)) {
                        echo "<a href=\"aktor.php?id=$row[0]\">";
                        echo "<div class=\"actor\">";
                        echo "<img src=\"$row[4]\" alt=\"$row[1] $row[2]\" title=\"$row[1] $row[2]\">";
                        echo "<p>$row[1] $row[2]</p>";
                        echo "</div>";
                        echo "</a>";
                    }
                    mysqli_close($connection);
                ?>
            </div>
        </main>
        <footer>
            <p>Autor: <strong>Bartosz Bryniarski</strong></p>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (index.php)
  38. Krok 38: aktor.php: połączenie w Skrypcie 2, zamknięcie w Skrypcie 3

    ok. 2 min
    Polecenie z arkusza

    Łączą się z serwerem bazodanowym na localhost, użytkownik root bez hasła, baza danych o nazwie kino. Na końcu skrypt zamyka połączenie z bazą

    Na aktor.php są dwa bloki PHP: Skrypt 2 wewnątrz bloku wszystkich aktorów i Skrypt 3 tuż pod nim, bo jego napis na ilustracji 4 stoi pod blokiem aktora. Połączenie otwiera Skrypt 2, a zamyka Skrypt 3 jako ostatnią operację na bazie. Zmienne PHP żyją przez całą stronę, więc $connection z pierwszego bloku działa też w drugim.

    aktor.php PHP zmienione: 6 linii
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <title>Informacje o aktorze | KinoTEKA</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <header id="logo">
            <h2><a href="index.php">KinoTEKA</a></h2>
        </header>
        <header id="motto">
            <p><em>W naszej bazie znajdują się najlepsi aktorzy</em></p>
        </header>
        <main>
            <div id="actors">
                <?php
                    $connection = mysqli_connect("localhost", "root", "", "kino");
                ?>
            </div>
            <?php
                mysqli_close($connection);
            ?>
        </main>
        <footer>
            <p>Autor: <strong>Bartosz Bryniarski</strong></p>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (aktor.php)
  39. Krok 39: Skrypt 2: zapytanie 2 z identyfikatorem z adresu

    Kryteria:

    R.5.4 Skrypt 2 lub skrypt 3 (podstrona) zawiera instrukcje wysyłającą odpowiednio zapytanie 2 lub 4 zmodyfikowane w ten sposób, że klauzula WHERE sprawdza wartość id z metody GET

    ok. 2 min
    Polecenie z arkusza

    Wysyła do bazy danych zapytanie 2 zmodyfikowane w ten sposób, aby uzyskiwać informacje o aktorze z identyfikatorem równym polu id pobranym metodą GET

    Parametry z adresu (aktor.php?id=10) PHP wkłada do tablicy $_GET; pod kluczem "id" jest więc to, co stoi po id=. Wartość trafia do zmiennej $id, a ta do zapytania 2 w miejsce trójki - PHP wstawia ją do napisu w cudzysłowach. Podgląd to strona otwarta z adresem aktor.php?id=10 (ilustracja 4); blok jest jeszcze pusty.

    Typowe błędy

    Otwarcie aktor.php bez ?id= w adresie daje ostrzeżenie „Undefined array key "id"”, a zapytanie z pustym warunkiem kończy się wyjątkiem „Uncaught mysqli_sql_exception” (sprawdzone w PHP 8.2). Klucz tego nie sprawdza - zabezpieczenie jest w etapie „Dobre praktyki”.

    aktor.php PHP zmienione: 3 linie
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <title>Informacje o aktorze | KinoTEKA</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <header id="logo">
            <h2><a href="index.php">KinoTEKA</a></h2>
        </header>
        <header id="motto">
            <p><em>W naszej bazie znajdują się najlepsi aktorzy</em></p>
        </header>
        <main>
            <div id="actors">
                <?php
                    $connection = mysqli_connect("localhost", "root", "", "kino");
                    $id = $_GET["id"];
                    $query = "SELECT imie, nazwisko, plik_awatara FROM aktorzy WHERE id_aktora = $id;";
                    $result = mysqli_query($connection, $query);
                ?>
            </div>
            <?php
                mysqli_close($connection);
            ?>
        </main>
        <footer>
            <p>Autor: <strong>Bartosz Bryniarski</strong></p>
        </footer>
    </body>
    </html>

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

  40. Krok 40: Skrypt 2: blok aktora z awatarem i nagłówkiem

    Kryteria:

    R.5.5 Skrypt 2 wyświetla jeden blok pojedynczego aktora z obrazem i danymi zwróconymi zapytaniem

    ok. 3 min
    Polecenie z arkusza

    Dla zwróconego z bazy wiersza tworzy blok pojedynczego aktora zawierający obraz, którego źródłem jest plik podany w kolumnie plik_awatara, z tekstem alternatywnym oraz atrybutem title z wartością „<IMIE> <NAZWISKO>” oraz nagłówek pierwszego stopnia zawierający tekst „<IMIE> <NAZWISKO>”

    Wiersz jest najwyżej jeden, więc zamiast pętli wystarczy jedno wywołanie mysqli_fetch_row. Numery kolumn liczą się teraz od pól zapytania 2, nie tabeli: $row[0] - imię, $row[1] - nazwisko, $row[2] - plik awatara. Blok ma klasę actor-profile (szerokość 25em), a nazwisko jest w <h1>. Podgląd: Pinto Teixeira jak na ilustracji 4.

    aktor.php PHP zmienione: 5 linii
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <title>Informacje o aktorze | KinoTEKA</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <header id="logo">
            <h2><a href="index.php">KinoTEKA</a></h2>
        </header>
        <header id="motto">
            <p><em>W naszej bazie znajdują się najlepsi aktorzy</em></p>
        </header>
        <main>
            <div id="actors">
                <?php
                    $connection = mysqli_connect("localhost", "root", "", "kino");
                    $id = $_GET["id"];
                    $query = "SELECT imie, nazwisko, plik_awatara FROM aktorzy WHERE id_aktora = $id;";
                    $result = mysqli_query($connection, $query);
                    $row = mysqli_fetch_row($result);
                    echo "<div class=\"actor-profile\">";
                    echo "<img src=\"$row[2]\" alt=\"$row[0] $row[1]\" title=\"$row[0] $row[1]\">";
                    echo "<h1>$row[0] $row[1]</h1>";
                    echo "</div>";
                ?>
            </div>
            <?php
                mysqli_close($connection);
            ?>
        </main>
        <footer>
            <p>Autor: <strong>Bartosz Bryniarski</strong></p>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (aktor.php)
  41. Krok 41: Skrypt 3: zapytanie 4 i liczba rekordów

    ok. 2 min
    Polecenie z arkusza

    Wysyła do bazy danych zapytanie 4 zmodyfikowane w taki sposób, że pobiera wyniki dotyczące aktora z identyfikatorem równym polu id pobranym metodą GET

    Zapytanie 4 z tą samą zmienną $id (odczytaną już w Skrypcie 2) w miejsce trójki. Skrypt nie wypisuje filmów, potrzebuje tylko ich liczby - mysqli_num_rows z tabeli 1 arkusza zwraca liczbę wierszy wyniku. Dla Pinto Teixeiry to 7.

    aktor.php PHP zmienione: 3 linie
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <title>Informacje o aktorze | KinoTEKA</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <header id="logo">
            <h2><a href="index.php">KinoTEKA</a></h2>
        </header>
        <header id="motto">
            <p><em>W naszej bazie znajdują się najlepsi aktorzy</em></p>
        </header>
        <main>
            <div id="actors">
                <?php
                    $connection = mysqli_connect("localhost", "root", "", "kino");
                    $id = $_GET["id"];
                    $query = "SELECT imie, nazwisko, plik_awatara FROM aktorzy WHERE id_aktora = $id;";
                    $result = mysqli_query($connection, $query);
                    $row = mysqli_fetch_row($result);
                    echo "<div class=\"actor-profile\">";
                    echo "<img src=\"$row[2]\" alt=\"$row[0] $row[1]\" title=\"$row[0] $row[1]\">";
                    echo "<h1>$row[0] $row[1]</h1>";
                    echo "</div>";
                ?>
            </div>
            <?php
                $query = "SELECT filmy.id_filmu, tytul, rok_produkcji FROM filmy JOIN filmy_aktorzy ON filmy.id_filmu = filmy_aktorzy.id_filmu WHERE filmy_aktorzy.id_aktora = $id;";
                $result = mysqli_query($connection, $query);
                $count = mysqli_num_rows($result);
                mysqli_close($connection);
            ?>
        </main>
        <footer>
            <p>Autor: <strong>Bartosz Bryniarski</strong></p>
        </footer>
    </body>
    </html>

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

  42. Krok 42: Skrypt 3: aktor bez żadnego filmu

    ok. 2 min
    Polecenie z arkusza

    Jeśli liczba rekordów uzyskanych zapytaniem wynosi 0, wyświetlany jest napis „<IMIE> nie znajduje się na listach obsady znanych nam produkcji.”, gdzie <IMIE> jest imieniem aktora pobranym w skrypcie 2

    Imię „pobrane w skrypcie 2” to wciąż $row[0] - Skrypt 3 nie odczytuje żadnego wiersza, więc tablica $row z bloku aktora jest nietknięta. Żeby zobaczyć ten napis, podgląd pokazuje stronę aktor.php?id=8: Lorenzo Di Romano nie ma żadnej pary w filmy_aktorzy (nie było go też w wyniku zapytania 5).

    aktor.php PHP zmienione: 3 linie
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <title>Informacje o aktorze | KinoTEKA</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <header id="logo">
            <h2><a href="index.php">KinoTEKA</a></h2>
        </header>
        <header id="motto">
            <p><em>W naszej bazie znajdują się najlepsi aktorzy</em></p>
        </header>
        <main>
            <div id="actors">
                <?php
                    $connection = mysqli_connect("localhost", "root", "", "kino");
                    $id = $_GET["id"];
                    $query = "SELECT imie, nazwisko, plik_awatara FROM aktorzy WHERE id_aktora = $id;";
                    $result = mysqli_query($connection, $query);
                    $row = mysqli_fetch_row($result);
                    echo "<div class=\"actor-profile\">";
                    echo "<img src=\"$row[2]\" alt=\"$row[0] $row[1]\" title=\"$row[0] $row[1]\">";
                    echo "<h1>$row[0] $row[1]</h1>";
                    echo "</div>";
                ?>
            </div>
            <?php
                $query = "SELECT filmy.id_filmu, tytul, rok_produkcji FROM filmy JOIN filmy_aktorzy ON filmy.id_filmu = filmy_aktorzy.id_filmu WHERE filmy_aktorzy.id_aktora = $id;";
                $result = mysqli_query($connection, $query);
                $count = mysqli_num_rows($result);
                if ($count == 0) {
                    echo "<p>$row[0] nie znajduje się na listach obsady znanych nam produkcji.</p>";
                }
                mysqli_close($connection);
            ?>
        </main>
        <footer>
            <p>Autor: <strong>Bartosz Bryniarski</strong></p>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (aktor.php)
  43. Krok 43: Skrypt 3: liczba filmów aktora

    Kryteria: , ,

    R.5.6 Skrypt 3: jeśli liczba rekordów zwrócona zapytaniem 4 wynosi 0 (Lorenzo Di Romano) , wyświetla tekst "<imie> nie znajduje się na listach obsady znanych nam produkcji.", a w przeciwnym wypadku wyświetla tekst "<imie> znajduje się na listach obsady <X> znanych nam produkcji."

    R.5.7 Skrypt 3 w miejscu <X> wyświetla liczbę rekordów zwróconą przesłanym zapytaniem

    R.5.8 W skryptach zastosowana przynajmniej jedna zmienna oraz nazwy wszystkich zmiennych są w języku polskim lub angielskim i odzwierciedlają cel zastosowania

    ok. 2 min
    Polecenie z arkusza

    W przeciwnym wypadku wyświetlany jest napis „<IMIE> znajduje się na listach obsady <X> znanych nam produkcji.”, gdzie <IMIE> jest imieniem aktora pobranym w skrypcie 2, a <X> oznacza liczbę rekordów uzyskanych zapytaniem 4

    Gałąź else wykonuje się dla każdej liczby różnej od zera, a w miejscu <X> stoi zmienna $count z mysqli_num_rows. Podgląd znów dla id 10: „Pinto znajduje się na listach obsady 7 znanych nam produkcji.” - jak na ilustracji 4. Wszystkie zmienne mają nazwy mówiące, co przechowują ($connection, $query, $result, $row, $id, $count) - to kryterium R.5.8.

    aktor.php PHP zmienione: 2 linie
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <title>Informacje o aktorze | KinoTEKA</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <header id="logo">
            <h2><a href="index.php">KinoTEKA</a></h2>
        </header>
        <header id="motto">
            <p><em>W naszej bazie znajdują się najlepsi aktorzy</em></p>
        </header>
        <main>
            <div id="actors">
                <?php
                    $connection = mysqli_connect("localhost", "root", "", "kino");
                    $id = $_GET["id"];
                    $query = "SELECT imie, nazwisko, plik_awatara FROM aktorzy WHERE id_aktora = $id;";
                    $result = mysqli_query($connection, $query);
                    $row = mysqli_fetch_row($result);
                    echo "<div class=\"actor-profile\">";
                    echo "<img src=\"$row[2]\" alt=\"$row[0] $row[1]\" title=\"$row[0] $row[1]\">";
                    echo "<h1>$row[0] $row[1]</h1>";
                    echo "</div>";
                ?>
            </div>
            <?php
                $query = "SELECT filmy.id_filmu, tytul, rok_produkcji FROM filmy JOIN filmy_aktorzy ON filmy.id_filmu = filmy_aktorzy.id_filmu WHERE filmy_aktorzy.id_aktora = $id;";
                $result = mysqli_query($connection, $query);
                $count = mysqli_num_rows($result);
                if ($count == 0) {
                    echo "<p>$row[0] nie znajduje się na listach obsady znanych nam produkcji.</p>";
                } else {
                    echo "<p>$row[0] znajduje się na listach obsady $count znanych nam produkcji.</p>";
                }
                mysqli_close($connection);
            ?>
        </main>
        <footer>
            <p>Autor: <strong>Bartosz Bryniarski</strong></p>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (aktor.php)
  44. Etap 5: Dobre praktyki (poza kluczem)

    Kroki 44-46 · po tym etapie masz 39 z 39 kryteriów (pkt)

    Krok 44: Identyfikator jako liczba i nieistniejący aktor

    ok. 4 min
    Polecenie z arkusza

    Korzysta z pola id przesłanego do pliku metodą GET

    Wersja egzaminacyjna sprawdzona na trzech „złych” adresach. aktor.php?id=3 OR 1=1 (spacje przeglądarka zakoduje sama) zamienia warunek w id_aktora = 3 OR 1=1: Skrypt 2 pokazuje pierwszego aktora z tabeli, Baptiste'a Lemoine'a, a Skrypt 3 liczy wszystkie pary w bazie - 84 „znanych produkcji”. Samo aktor.php bez parametru kończy się ostrzeżeniem „Undefined array key "id"” i błędem SQL, który urywa stronę, a aktor.php?id=99 - ostrzeżeniami „Trying to access array offset on value of type null”. Poprawki: (int) zamienia wartość z adresu na liczbę ("3 OR 1=1" → 3, brak parametru → 0 dzięki operatorowi ??), a warunek if ($row) wypisuje „Nie znaleziono aktora” i pomija Skrypt 3, gdy w bazie nie ma takiego identyfikatora. Podgląd: adres z 3 OR 1=1 pokazuje teraz Jerzego Paska i jego 11 filmów. Na egzaminie wystarczy wersja wcześniejsza - klucz tego nie sprawdza.

    aktor.php PHP zmienione: 18 linii
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <title>Informacje o aktorze | KinoTEKA</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <header id="logo">
            <h2><a href="index.php">KinoTEKA</a></h2>
        </header>
        <header id="motto">
            <p><em>W naszej bazie znajdują się najlepsi aktorzy</em></p>
        </header>
        <main>
            <div id="actors">
                <?php
                    $connection = mysqli_connect("localhost", "root", "", "kino");
                    $id = (int) ($_GET["id"] ?? 0);   // było: $id = $_GET["id"];
                    $query = "SELECT imie, nazwisko, plik_awatara FROM aktorzy WHERE id_aktora = $id;";
                    $result = mysqli_query($connection, $query);
                    $row = mysqli_fetch_row($result);
                    if ($row) {
                        echo "<div class=\"actor-profile\">";
                        echo "<img src=\"$row[2]\" alt=\"$row[0] $row[1]\" title=\"$row[0] $row[1]\">";
                        echo "<h1>$row[0] $row[1]</h1>";
                        echo "</div>";
                    } else {
                        echo "<h1>Nie znaleziono aktora</h1>";
                    }
                ?>
            </div>
            <?php
                if ($row) {
                    $query = "SELECT filmy.id_filmu, tytul, rok_produkcji FROM filmy JOIN filmy_aktorzy ON filmy.id_filmu = filmy_aktorzy.id_filmu WHERE filmy_aktorzy.id_aktora = $id;";
                    $result = mysqli_query($connection, $query);
                    $count = mysqli_num_rows($result);
                    if ($count == 0) {
                        echo "<p>$row[0] nie znajduje się na listach obsady znanych nam produkcji.</p>";
                    } else {
                        echo "<p>$row[0] znajduje się na listach obsady $count znanych nam produkcji.</p>";
                    }
                }
                mysqli_close($connection);
            ?>
        </main>
        <footer>
            <p>Autor: <strong>Bartosz Bryniarski</strong></p>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (aktor.php)
  45. Krok 45: Zapytania przygotowane w Skryptach 2 i 3

    ok. 3 min
    Polecenie z arkusza

    Wysyła do bazy danych zapytanie 4 zmodyfikowane w taki sposób, że pobiera wyniki dotyczące aktora z identyfikatorem równym polu id pobranym metodą GET

    Rzutowanie (int) już zamknęło drogę wstrzyknięciu, ale w prawdziwych projektach wartości od użytkownika w ogóle nie wkleja się do treści SQL. Zapytanie przygotowane: mysqli_prepare wysyła zapytanie ze znakiem ? w miejscu identyfikatora, mysqli_stmt_bind_param z typem "i" (liczba całkowita) dokłada wartość osobno, a mysqli_stmt_get_result oddaje zwykły wynik - dalszy kod (mysqli_fetch_row, mysqli_num_rows) zostaje bez zmian. Stare linie zostają w komentarzu. Na egzaminie wystarczy wersja wcześniejsza - klucz tego nie sprawdza.

    aktor.php PHP zmienione: 12 linii
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <title>Informacje o aktorze | KinoTEKA</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <header id="logo">
            <h2><a href="index.php">KinoTEKA</a></h2>
        </header>
        <header id="motto">
            <p><em>W naszej bazie znajdują się najlepsi aktorzy</em></p>
        </header>
        <main>
            <div id="actors">
                <?php
                    $connection = mysqli_connect("localhost", "root", "", "kino");
                    $id = (int) ($_GET["id"] ?? 0);   // było: $id = $_GET["id"];
                    $statement = mysqli_prepare($connection, "SELECT imie, nazwisko, plik_awatara FROM aktorzy WHERE id_aktora = ?");
                    mysqli_stmt_bind_param($statement, "i", $id);
                    mysqli_stmt_execute($statement);
                    $result = mysqli_stmt_get_result($statement);
                    // $query = "SELECT imie, nazwisko, plik_awatara FROM aktorzy WHERE id_aktora = $id;";
                    // $result = mysqli_query($connection, $query);
                    $row = mysqli_fetch_row($result);
                    if ($row) {
                        echo "<div class=\"actor-profile\">";
                        echo "<img src=\"$row[2]\" alt=\"$row[0] $row[1]\" title=\"$row[0] $row[1]\">";
                        echo "<h1>$row[0] $row[1]</h1>";
                        echo "</div>";
                    } else {
                        echo "<h1>Nie znaleziono aktora</h1>";
                    }
                ?>
            </div>
            <?php
                if ($row) {
                    $statement = mysqli_prepare($connection, "SELECT filmy.id_filmu, tytul, rok_produkcji FROM filmy JOIN filmy_aktorzy ON filmy.id_filmu = filmy_aktorzy.id_filmu WHERE filmy_aktorzy.id_aktora = ?");
                    mysqli_stmt_bind_param($statement, "i", $id);
                    mysqli_stmt_execute($statement);
                    $result = mysqli_stmt_get_result($statement);
                    // $query = "SELECT filmy.id_filmu, tytul, rok_produkcji FROM filmy JOIN filmy_aktorzy ON filmy.id_filmu = filmy_aktorzy.id_filmu WHERE filmy_aktorzy.id_aktora = $id;";
                    // $result = mysqli_query($connection, $query);
                    $count = mysqli_num_rows($result);
                    if ($count == 0) {
                        echo "<p>$row[0] nie znajduje się na listach obsady znanych nam produkcji.</p>";
                    } else {
                        echo "<p>$row[0] znajduje się na listach obsady $count znanych nam produkcji.</p>";
                    }
                }
                mysqli_close($connection);
            ?>
        </main>
        <footer>
            <p>Autor: <strong>Bartosz Bryniarski</strong></p>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (aktor.php)
  46. Krok 46: index.php: kolumny po nazwach i htmlspecialchars

    ok. 3 min
    Polecenie z arkusza

    Obraz, którego źródłem jest plik podany w kolumnie plik_awatara, z tekstem alternatywnym oraz atrybutem title z wartością „<IMIE> <NAZWISKO>” (Ilustracja 2, awatar 2)

    Przy SELECT * numer kolumny zależy od kolejności pól w tabeli - wystarczy, że ktoś doda pole, i $row[4] przestaje być plikiem awatara. mysqli_fetch_assoc oddaje wiersz z kluczami takimi jak nazwy kolumn ($actor["plik_awatara"]). Imię i nazwisko trafiają do atrybutów alt i title w cudzysłowach, więc nazwisko z cudzysłowem albo znakiem < rozbiłoby znacznik - htmlspecialchars zamienia takie znaki na encje (&quot;, &lt;). Litery „ï” i „É” zostają bez zmian. Na egzaminie wystarczy wersja wcześniejsza - klucz tego nie sprawdza.

    index.php PHP zmienione: 7 linii
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <title>Lista aktorów | KinoTEKA</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <header id="logo">
            <h2><a href="index.php">KinoTEKA</a></h2>
        </header>
        <header id="motto">
            <p><em>W naszej bazie znajdują się najlepsi aktorzy</em></p>
        </header>
        <main>
            <h1>Najlepsi aktorzy tylko w naszym kinie</h1>
            <div id="actors">
                <?php
                    $connection = mysqli_connect("localhost", "root", "", "kino");
                    $query = "SELECT * FROM aktorzy ORDER BY nazwisko, imie;";
                    $result = mysqli_query($connection, $query);
                    while ($actor = mysqli_fetch_assoc($result)) {
                        $name = htmlspecialchars($actor["imie"] . " " . $actor["nazwisko"]);
                        $avatar = htmlspecialchars($actor["plik_awatara"]);
                        echo "<a href=\"aktor.php?id=" . $actor["id_aktora"] . "\">";
                        echo "<div class=\"actor\">";
                        echo "<img src=\"$avatar\" alt=\"$name\" title=\"$name\">";
                        echo "<p>$name</p>";
                        echo "</div>";
                        echo "</a>";
                    }
                    // while ($row = mysqli_fetch_row($result)) { ... "$row[1] $row[2]" ... }
                    mysqli_close($connection);
                ?>
            </div>
        </main>
        <footer>
            <p>Autor: <strong>Bartosz Bryniarski</strong></p>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (index.php)
  47. Etap 6: Oddanie pracy

    Krok 47 · po tym etapie masz 39 z 39 kryteriów (pkt)

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

    ok. 5 min
    Polecenie z arkusza

    Po zakończeniu pracy utwórz plik tekstowy o nazwie przeglądarka.txt. Zapisz w nim nazwę przeglądarki internetowej, w której weryfikowana była poprawność działania witryny. Umieść go w folderze z numerem zdającego. Nagraj płytę z rezultatami pracy.

    W przeglądarka.txt wystarczy nazwa przeglądarki, w której była sprawdzana strona.

    W folderze z numerem zdającego: aktor.php, import.png, index.php, kwerendy.txt, kw1.jpg - kw5.jpg, przeglądarka.txt, styl.css i pliki awatarów awatar_1.jpg - awatar_10.jpg. Po nagraniu płyty trzeba sprawdzić jej odczyt i opisać ją numerem zdającego.

    przeglądarka.txt Tekst nowy plik
    Google Chrome

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

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.