Przejdź do głównej treści
EE.09-01-23.01-SGStyczeń 2023 · 34 kroki · ok. 78 min · 37 kryteriów z klucza

Rozwiązanie krok po kroku: Akta pracownicze dla sekretariatu firmy (Nowoczesny kod (grid, PDO))

To drugi sposób rozwiązania tego samego arkusza. Wynik jest ten sam - baza firma z czterema zapytaniami, zdjęcie przeskalowane do 400 px i strona index.php z danymi pracownika, liczbą zatrudnionych i stanowiskiem - i tak samo spełnia każde kryterium klucza. Inna jest droga:

  • siatka CSS zamiast float: bloki lewy i prawy stoją w znaczniku <main> z grid-template-columns: 50% 30%, a stopka nie potrzebuje clear,
  • cała praca z bazą na górze pliku, przed HTML-em: PDO, cztery zapytania i zamknięcie połączenia; w miejscach skryptów 1-3 zostaje samo wypisywanie danych,
  • zapytania przygotowane z numerem pracownika w zmiennej - gotowe na chwilę, gdy numer przyjdzie z adresu strony,
  • funkcja e() (skrót od escape) przepuszcza każdą wartość z bazy przez htmlspecialchars, zanim trafi do HTML-u,
  • błąd połączenia daje na stronie jeden czytelny komunikat zamiast komunikatu PHP z nazwą użytkownika bazy i ścieżką pliku.

To arkusz EE.09 ze stycznia 2023 - kwalifikacji formuły 2017, którą zastąpiła INF.03. Baza, zdjęcie i cv.txt pochodzą z oryginalnego archiwum CKE zad1.zip (załącznik na stronie arkusza), zapytania i zrzuty są policzone na MariaDB 10.4, a podgląd od kroków z PHP to wynik prawdziwego uruchomienia kodu w PHP 8.2 (klucz każe sprawdzać w XAMPP 8.1.2 - użyte konstrukcje działają w obu wersjach).

Jak liczą się punkty. Klucz ma 37 kryteriów (R.1.1 - R.5.9), każde za 1 punkt. Próg zdania części praktycznej to 75%, czyli 28 punktów. Przy każdym kroku jest napisane, które kryteria spełnia; klucz przyjmuje zarówno mysqli, jak i PDO.

  1. Etap 1: Baza danych

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

    Krok 1: Folder zdającego i archiwum zad1.zip

    ok. 2 min
    Polecenie z arkusza

    Na pulpicie konta Egzamin należy utworzyć folder. Jako nazwy folderu należy użyć numeru zdającego, którym został podpisany arkusz. Rozpakowane pliki należy umieścić w tym folderze. Zaleca się, aby rozpakowane pliki znajdowały się w tym samym folderze, co pliki strony. Po skończonej pracy wszystkie wyniki należy zapisać w tym folderze.

    Folder na pulpicie nazwany numerem zdającego (w tym rozwiązaniu Bartosz Bryniarski), do niego zad1.zip z hasłem AKt@PR@cownicZE: baza.sql, 2.jpg i cv.txt. Strona PHP działa przez Apache, więc pracuj w folderze w C:\xampp\htdocs, a na koniec skopiuj całość do folderu z numerem.

  2. Krok 2: XAMPP i baza firma

    ok. 2 min
    Polecenie z arkusza

    Za pomocą narzędzia phpMyAdmin wykonaj operacje na bazie danych: Utwórz bazę danych o nazwie firma

    Start przy Apache i MySQL, http://localhost/phpmyadmin, Nowa, nazwa firma, porównywanie np. utf8_polish_ci.

  3. Krok 3: Import tabel z pliku baza.sql i zrzut import.jpg

    Kryteria:

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

    ok. 3 min
    Polecenie z arkusza

    Do bazy firma zaimportuj tabele z pliku baza.sql z rozpakowanego archiwum. Wykonaj zrzut ekranu po imporcie. Zrzut zapisz w formacie JPEG i nazwij 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

    Karta Import bazy firma, plik baza.sql. Dwie tabele: pracownicy (9 wierszy, klucz obcy stanowiska_id) i stanowiska (4). Zrzut całego ekranu z komunikatem o sukcesie: import.jpg.

    Podgląd strony po tym kroku
    Podgląd strony po kroku 3
  4. Krok 4: Zapytanie 1: dane pracownika o id 2

    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, adres, miasto, czyRODO, czyBadania z tabeli pracownicy dla wiersza o id równym 2. W pliku z kwerendami lub na zrzucie istnieje zapis np.: SELECT imie, nazwisko, adres, miasto, czyRODO, czyBadania FROM pracownicy WHERE id=2; oraz wynik działania zapytania udokumentowano zrzutem, na którym widoczny jest jedynie rekord z danymi: Anna, Nowak, ul. Piekarska 6, Bytom, 1, 1

    ok. 3 min
    Polecenie z arkusza

    Wykonaj zapytania SQL działające na bazie firma. Zapytania zapisz w pliku kwerendy.txt. 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, adres, miasto, czyRODO, czyBadania z tabeli pracownicy dla wiersza o id równym 2

    Sześć pól w kolejności z arkusza, każda klauzula w osobnej linii. Wynik: Anna, Nowak, ul. Piekarska 6, Bytom, 1, 1. Zapytanie do kwerendy.txt, zrzut: kw1.png.

    kwerendy.txt Tekst nowy plik
    -- Zapytanie 1
    SELECT imie, nazwisko, adres, miasto, czyRODO, czyBadania
    FROM pracownicy
    WHERE id = 2;
    Podgląd strony po tym kroku
    Podgląd strony po kroku 4
  5. Krok 5: Zapytanie 2: liczba pracowników

    Kryteria:

    R.1.4 Utworzono zapytanie 2 zliczające wszystkie rekordy w tabeli pracownicy . W pliku z kwerendami lub na zrzucie istnieje zapis np.: SELECT COUNT(*) FROM pracownicy; (możliwa też nazwa dowolnego pola zamiast *) oraz wynik działania zapytania udokumentowano zrzutem, na którym widoczna jest wartość 9

    ok. 3 min
    Polecenie z arkusza

    Zapytanie 2: wybierające liczbę wszystkich rekordów w tabeli pracownicy

    COUNT(*) - wynik 9. Zrzut: kw2.png.

    kwerendy.txt Tekst zmienione: 4 linie
    -- Zapytanie 1
    SELECT imie, nazwisko, adres, miasto, czyRODO, czyBadania
    FROM pracownicy
    WHERE id = 2;
    
    -- Zapytanie 2
    SELECT COUNT(*)
    FROM pracownicy;
    Podgląd strony po tym kroku
    Podgląd strony po kroku 5
  6. Krok 6: Zapytanie 3: id, imię i nazwisko pracownika o id 2

    Kryteria:

    R.1.5 Utworzono zapytanie 3 wybierające jedynie pola id, imie, nazwisko z tabeli pracownicy dla wiersza o id równym 2. W pliku z kwerendami lub na zrzucie istnieje zapis np.: SELECT id, imie, nazwisko FROM pracownicy WHERE id = 2; oraz wynik działania zapytania udokumentowano zrzutem, na którym widoczny jest jedynie jeden rekord z danymi: 2, Anna, Nowak

    ok. 3 min
    Polecenie z arkusza

    Zapytanie 3: wybierające jedynie pola id, imie, nazwisko z tabeli pracownicy dla wiersza o id równym 2

    Wynik: 2, Anna, Nowak. Zrzut: kw3.png.

    kwerendy.txt Tekst zmienione: 5 linii
    -- Zapytanie 1
    SELECT imie, nazwisko, adres, miasto, czyRODO, czyBadania
    FROM pracownicy
    WHERE id = 2;
    
    -- Zapytanie 2
    SELECT COUNT(*)
    FROM pracownicy;
    
    -- Zapytanie 3
    SELECT id, imie, nazwisko
    FROM pracownicy
    WHERE id = 2;
    Podgląd strony po tym kroku
    Podgląd strony po kroku 6
  7. Krok 7: Zapytanie 4: stanowisko pracownika przez relację

    Kryteria:

    R.1.6 Utworzono zapytanie 4 wybierające jedynie pole id z tabeli pracownicy i odpowiadające mu pola nazwa i opis z tabeli stanowiska dla wiersza tabeli pracownicy o id równym 2. W pliku z kwerendami lub na zrzucie istnieje zapis np.: SELECT pracownicy.id, nazwa, opis FROM pracownicy JOIN stanowiska ON pracownicy.stanowiska_id = stanowiska.id WHERE pracownicy.id = 2; (możliwe też INNER JOIN lub bez JOIN z porównaniem kluczy w sekcji WHERE) oraz wynik działania zapytania udokumentowano zrzutem, na którym widoczny jest jedynie jeden rekord z danymi: 2, kierownik, kierownik grupy programistow

    ok. 3 min
    Polecenie z arkusza

    Zapytanie 4: wybierające jedynie id z tabeli pracownicy i odpowiadające mu pola nazwa i opis z tabeli stanowiska dla wiersza tabeli pracownicy o id równym 2. Należy posłużyć się relacją

    JOIN … ON pracownicy.stanowiska_id = stanowiska.id, a id zawsze z nazwą tabeli - mają je obie. Wynik: 2, kierownik, kierownik grupy programistow. Zrzut: kw4.png.

    kwerendy.txt Tekst zmienione: 6 linii
    -- Zapytanie 1
    SELECT imie, nazwisko, adres, miasto, czyRODO, czyBadania
    FROM pracownicy
    WHERE id = 2;
    
    -- Zapytanie 2
    SELECT COUNT(*)
    FROM pracownicy;
    
    -- Zapytanie 3
    SELECT id, imie, nazwisko
    FROM pracownicy
    WHERE id = 2;
    
    -- Zapytanie 4
    SELECT pracownicy.id, nazwa, opis
    FROM pracownicy
    JOIN stanowiska ON pracownicy.stanowiska_id = stanowiska.id
    WHERE pracownicy.id = 2;
    Podgląd strony po tym kroku
    Podgląd strony po kroku 7
  8. Etap 2: Grafika i strona HTML

    Kroki 8-14 · po tym etapie masz 15 z 37 kryteriów (pkt)

    Krok 8: Zdjęcie 2.jpg przeskalowane do 400 px

    Kryteria:

    R.2.1 Plik 2 .jpg przeskalowano z zachowaniem proporcji do szerokości 400 px, odpowiadająca temu wysokość wynosi 267 px (± 5 px)

    ok. 2 min
    Polecenie z arkusza

    Plik 2.jpg, wypakowany z archiwum, należy przeskalować z zachowaniem proporcji do szerokości 400 px

    Obraz → Skaluj obraz z zamkniętym łańcuchem: 500 × 334 px → 400 × 267 px (klucz: 267 ±5), zapis pod tą samą nazwą (Plik → Nadpisz 2.jpg).

    Podgląd strony po tym kroku
    Podgląd strony po kroku 8
  9. Krok 9: Plik index.php

    Kryteria:

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

    ok. 1 min
    Polecenie z arkusza

    Cechy witryny: Składa się ze strony o nazwie index.php

    Nowy plik index.php obok zdjęcia i cv.txt.

    index.php PHP nowy plik
    Podgląd strony po tym kroku (index.php)
  10. Krok 10: Szkielet HTML5, kodowanie i język

    Kryteria:

    R.2.3 Zastosowano deklarację języka HTML5, jawnie zapisano standard kodowania polskich znaków oraz zadeklarowano język witryny (np. <html lang = 'pl'>)

    ok. 2 min
    Polecenie z arkusza

    Zapisana w języku HTML5. Jawnie zastosowany właściwy standard kodowania polskich znaków. Zadeklarowany język witryny: polski

    Trzy zdania arkusza w jednym szkielecie: <!DOCTYPE html>, lang="pl" i <meta charset="UTF-8">. Linia viewport każe telefonowi wyświetlić stronę w szerokości ekranu - arkusz jej nie wymaga.

    index.php PHP zmienione: 9 linii
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
    </head>
    <body>
    </body>
    </html>
    Podgląd strony po tym kroku (index.php)
  11. Krok 11: Tytuł strony i arkusz stylów

    Kryteria: ,

    R.2.4 Nadano tytuł stronie: "Sekretariat"

    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 zdający źle przypisał co najmniej jeden selektor do bloku (np. kropka zamiast #)

    ok. 1 min
    Polecenie z arkusza

    Tytuł strony widoczny na karcie przeglądarki: „Sekretariat”. Arkusz stylów w pliku o nazwie styl.css prawidłowo połączony z kodem strony

    <title> i <link> do styl.css - całe formatowanie w tym pliku, bez atrybutów style.

    index.php PHP zmienione: 2 linie
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>Sekretariat</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
    </body>
    </html>
    Podgląd strony po tym kroku (index.php)
  12. Krok 12: Bloki: główna część z dwiema sekcjami i stopka

    Kryteria:

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

    ok. 2 min
    Polecenie z arkusza

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

    Bloki lewy i prawy - <section> z identyfikatorami left i right - stoją we wspólnym <main>, który w CSS stanie się siatką z dwiema kolumnami. Stopka <footer> jest za <main>.

    index.php PHP zmienione: 8 linii
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>Sekretariat</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <main>
            <section id="left">
            </section>
            <section id="right">
            </section>
        </main>
        <footer>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (index.php)
  13. Krok 13: Blok lewy: nagłówki, linia, odnośnik i paragraf

    Kryteria:

    R.3.2 Na stronie umieszczono odnośnik, którego kliknięcie otwiera / pobiera plik cv.txt

    ok. 3 min
    Polecenie z arkusza

    Zawartość bloku lewego: nagłówek pierwszego stopnia o treści „Akta Pracownicze”, dane pracownika generowane skryptem 1, linia horyzontalna, nagłówek trzeciego stopnia o treści: „Dokumenty pracownika”, odnośnik o treści „Pobierz” do pliku cv.txt, nagłówek pierwszego stopnia o treści „Liczba zatrudnionych pracowników”, paragraf, a w nim efekt wykonania skryptu 2

    Stała część bloku lewego w kolejności z arkusza: <h1>, linia <hr>, <h3>, odnośnik do cv.txt (otwiera albo pobiera plik - R.3.2), drugi <h1> i pusty paragraf na liczbę pracowników. Miejsce na dane pracownika jest między pierwszym nagłówkiem a linią - wypełni je etap PHP.

    cv.txt Tekst nowy plik
    plik z CV pracownika
    index.php PHP zmienione: 6 linii
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>Sekretariat</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <main>
            <section id="left">
                <h1>Akta Pracownicze</h1>
                <hr>
                <h3>Dokumenty pracownika</h3>
                <a href="cv.txt">Pobierz</a>
                <h1>Liczba zatrudnionych pracowników</h1>
                <p></p>
            </section>
            <section id="right">
            </section>
        </main>
        <footer>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (index.php)
  14. Krok 14: Stopka: autor i lista punktowana

    Kryteria: ,

    R.2.7 W bloku stopki umieszczono listę punktowaną z dwoma elementami, zastosowano znaczniki <ul>, <li>

    R.2.9 W stopce umieszczono napis "Autorem aplikacji jest: "

    ok. 2 min
    Polecenie z arkusza

    Zawartość stopki: napis o treści „Autorem aplikacji jest: ”, dalej wstawiony numer zdającego, lista punktowana (nieuporządkowana) o elementach: „skontaktuj się”, „poznaj naszą firmę”

    Napis bez paragrafu (reguła dla p dodałaby wcięcie) z Bartosz Bryniarski w miejscu numeru PESEL i lista <ul> z dwoma <li>.

    index.php PHP zmienione: 5 linii
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>Sekretariat</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <main>
            <section id="left">
                <h1>Akta Pracownicze</h1>
                <hr>
                <h3>Dokumenty pracownika</h3>
                <a href="cv.txt">Pobierz</a>
                <h1>Liczba zatrudnionych pracowników</h1>
                <p></p>
            </section>
            <section id="right">
            </section>
        </main>
        <footer>
            Autorem aplikacji jest: Bartosz Bryniarski
            <ul>
                <li>skontaktuj się</li>
                <li>poznaj naszą firmę</li>
            </ul>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (index.php)
  15. Etap 3: Styl CSS

    Kroki 15-21 · po tym etapie masz 26 z 37 kryteriów (pkt)

    Krok 15: Zmienne z kolorami i styl strony

    Kryteria:

    R.4.1 Ustawiono dla selektora strony (body lub html lub kontener strony) krój czcionki Helvetica, kolor tła #DDD, kolor czcionki #546E7A

    ok. 2 min
    Polecenie z arkusza

    Styl CSS powinien być zdefiniowany jedynie w zewnętrznym pliku CSS. Dla selektora strony: krój czcionki Helvetica, kolor tła #DDD, kolor czcionki #546E7A

    Niebieski z arkusza (#5C6BC0, stopka i paski nagłówków) i kolor tekstu w zmiennych na :root. Krój Helvetica pierwszy, za nim zastępcze: Helvetica rzadko jest w Windows, więc przeglądarka weźmie Arial - zbliżony krój bezszeryfowy.

    styl.css CSS nowy plik
    :root {
        --accent: #5C6BC0;
        --text: #546E7A;
    }
    
    body {
        font-family: Helvetica, Arial, sans-serif;
        background-color: #DDD;
        color: var(--text);
    }
    Podgląd strony po tym kroku (index.php)
  16. Krok 16: Bloki obok siebie: siatka 50% i 30%

    Kryteria: ,

    R.3.1 Układ bloków po uruchomieniu strony w przeglądarce jest zgodny z Obrazem 2 w arkuszu egzaminacyjnym (prawidłowo zastosowano właściwości css układające bloki na stronie, np. float i clear albo display flex albo grid)

    R.4.5 Ustawiono szerokość bloku lewego: 50%, prawego 30% (width lub grid-template-columns lub flex)

    ok. 3 min
    Polecenie z arkusza

    Dla bloku lewego: szerokość 50%. Dla bloku prawego: szerokość 30%

    display: grid z grid-template-columns: 50% 30% - dwie kolumny o szerokościach z arkusza; klucz przyjmuje je w tej postaci (R.4.5) i wymienia siatkę wśród sposobów ułożenia bloków (R.3.1). Stopka stoi pod siatką bez clear.

    Jedna różnica wobec wersji podstawowej: margines 20 px bloku mieści się w kolumnie, więc blok ma 50% szerokości minus 40 px, a nie pełne 50%. Przy float z width: 50% margines dolicza się na zewnątrz. Układ na ekranie jest taki sam jak na obrazie 2 - klucz sprawdza ustawione szerokości, nie piksele.

    styl.css CSS zmienione: 5 linii
    :root {
        --accent: #5C6BC0;
        --text: #546E7A;
    }
    
    body {
        font-family: Helvetica, Arial, sans-serif;
        background-color: #DDD;
        color: var(--text);
    }
    
    main {
        display: grid;
        grid-template-columns: 50% 30%;
    }
    Podgląd strony po tym kroku (index.php)
  17. Krok 17: Bloki lewy i prawy: tło, wysokość, marginesy i cień

    Kryteria: ,

    R.4.4 Ustawiono wysokość bloku lewego i prawego: 600px

    R.4.8 Ustawiono dla bloku lewego i prawego cień o cechach: przesunięcie poziome i pionowe 0, rozmycie 20px kolor szary (dowolny odcień) np. box-shadow: 0 0 20px grey; (lub 0 0 20px 0 grey, lub gray, lub inny dowolny szary)

    ok. 2 min
    Polecenie z arkusza

    Wspólne dla bloku lewego i prawego: biały kolor tła, wysokość 600 px, marginesy zewnętrzne 20 px, cień bloku bez przesunięcia pionowego i poziomego, rozmycie 20 px i kolor szary

    box-shadow: 0 0 20px gray - przesunięcia 0, rozmycie 20 px, kolor (kolejność z pomocy w3schools w arkuszu).

    styl.css CSS zmienione: 7 linii
    :root {
        --accent: #5C6BC0;
        --text: #546E7A;
    }
    
    body {
        font-family: Helvetica, Arial, sans-serif;
        background-color: #DDD;
        color: var(--text);
    }
    
    main {
        display: grid;
        grid-template-columns: 50% 30%;
    }
    
    #left, #right {
        background-color: white;
        height: 600px;
        margin: 20px;
        box-shadow: 0 0 20px gray;
    }
    Podgląd strony po tym kroku (index.php)
  18. Krok 18: Stopka

    ok. 1 min
    Polecenie z arkusza

    Dla stopki: kolor tła #5C6BC0, biały kolor czcionki, marginesy wewnętrzne 30px

    Kolor ze zmiennej --accent.

    styl.css CSS zmienione: 6 linii
    :root {
        --accent: #5C6BC0;
        --text: #546E7A;
    }
    
    body {
        font-family: Helvetica, Arial, sans-serif;
        background-color: #DDD;
        color: var(--text);
    }
    
    main {
        display: grid;
        grid-template-columns: 50% 30%;
    }
    
    #left, #right {
        background-color: white;
        height: 600px;
        margin: 20px;
        box-shadow: 0 0 20px gray;
    }
    
    footer {
        background-color: var(--accent);
        color: white;
        padding: 30px;
    }
    Podgląd strony po tym kroku (index.php)
  19. Krok 19: Obraz: szerokość 100%

    Kryteria:

    R.4.9 Ustawiono dla selektora obrazu szerokość 100%

    ok. 1 min
    Polecenie z arkusza

    Dla selektora obrazu: szerokość 100%

    width: 100% z arkusza (R.4.9) i display: block - obraz jest domyślnie elementem w linii tekstu i zostawia pod sobą kilka pikseli odstępu na „ogonki” liter; jako blok przylega do nagłówka pod nim.

    styl.css CSS zmienione: 5 linii
    :root {
        --accent: #5C6BC0;
        --text: #546E7A;
    }
    
    body {
        font-family: Helvetica, Arial, sans-serif;
        background-color: #DDD;
        color: var(--text);
    }
    
    main {
        display: grid;
        grid-template-columns: 50% 30%;
    }
    
    #left, #right {
        background-color: white;
        height: 600px;
        margin: 20px;
        box-shadow: 0 0 20px gray;
    }
    
    footer {
        background-color: var(--accent);
        color: white;
        padding: 30px;
    }
    
    img {
        width: 100%;
        display: block;
    }
    Podgląd strony po tym kroku (index.php)
  20. Krok 20: Nagłówek pierwszego stopnia

    Kryteria: , ,

    R.4.2 Ustawiono kolor tła: biały dla bloku lewego i prawego, #5C6BC0 dla stopki oraz dla selektora h1

    R.4.3 Ustawiono biały kolor czcionki dla stopki oraz h1

    R.4.10 Ustawiono dla h1 grubość czcionki na 300

    ok. 1 min
    Polecenie z arkusza

    Dla selektora nagłówka pierwszego stopnia: kolor tła #5C6BC0, biały kolor czcionki, marginesy wewnętrzne 10 px, brak marginesów zewnętrznych, grubość czcionki 300

    Pasek w kolorze stopki, margin: 0 i cieńsze litery font-weight: 300.

    styl.css CSS zmienione: 8 linii
    :root {
        --accent: #5C6BC0;
        --text: #546E7A;
    }
    
    body {
        font-family: Helvetica, Arial, sans-serif;
        background-color: #DDD;
        color: var(--text);
    }
    
    main {
        display: grid;
        grid-template-columns: 50% 30%;
    }
    
    #left, #right {
        background-color: white;
        height: 600px;
        margin: 20px;
        box-shadow: 0 0 20px gray;
    }
    
    footer {
        background-color: var(--accent);
        color: white;
        padding: 30px;
    }
    
    img {
        width: 100%;
        display: block;
    }
    
    h1 {
        background-color: var(--accent);
        color: white;
        padding: 10px;
        margin: 0;
        font-weight: 300;
    }
    Podgląd strony po tym kroku (index.php)
  21. Krok 21: Wcięcie h3 i p, wyśrodkowanie h2 i h4

    Kryteria: ,

    R.4.6 Ustawiono wyrównanie tekstu do środka dla selektora h2 i h4

    R.4.7 Ustawiono marginesy zewnętrzne (margin) 20px dla bloku lewego i prawego; 0 dla h1 oraz marginesy wewnętrzne (padding) 30px dla stopki; 10px dla h1; lewy 30px (padding-left) dla selektora h3 i selektora p (wystarczy 5 z 7 cech)

    ok. 1 min
    Polecenie z arkusza

    Dla selektora nagłówka trzeciego stopnia i paragrafu (akapitu): margines wewnętrzny lewy 30 px. Dla selektora nagłówka drugiego i czwartego stopnia: wyrównanie tekstu do środka

    Same selektory znaczników, bez klas - arkusz to zastrzega.

    styl.css CSS zmienione: 8 linii
    :root {
        --accent: #5C6BC0;
        --text: #546E7A;
    }
    
    body {
        font-family: Helvetica, Arial, sans-serif;
        background-color: #DDD;
        color: var(--text);
    }
    
    main {
        display: grid;
        grid-template-columns: 50% 30%;
    }
    
    #left, #right {
        background-color: white;
        height: 600px;
        margin: 20px;
        box-shadow: 0 0 20px gray;
    }
    
    footer {
        background-color: var(--accent);
        color: white;
        padding: 30px;
    }
    
    img {
        width: 100%;
        display: block;
    }
    
    h1 {
        background-color: var(--accent);
        color: white;
        padding: 10px;
        margin: 0;
        font-weight: 300;
    }
    
    h3, p {
        padding-left: 30px;
    }
    
    h2, h4 {
        text-align: center;
    }
    Podgląd strony po tym kroku (index.php)
  22. Etap 4: Skrypty PHP

    Kroki 22-32 · po tym etapie masz 37 z 37 kryteriów (pkt)

    Krok 22: Połączenie z bazą firma na górze pliku

    Kryteria: ,

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

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

    ok. 4 min
    Polecenie z arkusza

    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 firma. Po wykonaniu operacji na bazie danych skrypt zamyka połączenie z serwerem.

    Cała praca z bazą idzie na górę pliku, przed <!DOCTYPE html>: najpierw dane, potem HTML, który je tylko wypisuje.

    • $id = 2 - numer pracownika w jednym miejscu, użyją go trzy zapytania,
    • new PDO(…) - połączenie: serwer localhost, baza firma i kodowanie utf8mb4 w pierwszym napisie, potem użytkownik root i puste hasło (R.5.1),
    • ERRMODE_EXCEPTION - błąd bazy rzuca wyjątek, FETCH_ASSOC - wiersze jako tablice z nazwami kolumn ($employee['imie'] zamiast $row[0]),
    • try … catch - gdy serwer bazy nie działa, zamiast komunikatu PHP z nazwą użytkownika i ścieżką pliku strona dostanie spokojny komunikat w $error,
    • finally { $pdo = null; } - przypisanie null zamyka połączenie PDO, a blok finally wykona się zawsze, także po błędzie. To ostatnia operacja na bazie (R.5.2); zapytania staną nad nią, w bloku try.

    Klucz przyjmuje bibliotekę PDO. Połączenie stoi w pliku strony, bez osobnego pliku konfiguracyjnego - klucz sprawdza połączenie w kodzie strony. Od tego kroku podgląd to wynik strony z serwera PHP 8.2.

    index.php PHP zmienione: 15 linii
    <?php
    $id = 2;
    $error = '';
    
    try {
        $pdo = new PDO('mysql:host=localhost;dbname=firma;charset=utf8mb4', 'root', '', [
            PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
            PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
        ]);
    } catch (PDOException $exception) {
        $error = 'Brak połączenia z bazą danych - spróbuj później.';
    } finally {
        $pdo = null;
    }
    ?>
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>Sekretariat</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <main>
            <section id="left">
                <h1>Akta Pracownicze</h1>
                <hr>
                <h3>Dokumenty pracownika</h3>
                <a href="cv.txt">Pobierz</a>
                <h1>Liczba zatrudnionych pracowników</h1>
                <p></p>
            </section>
            <section id="right">
            </section>
        </main>
        <footer>
            Autorem aplikacji jest: Bartosz Bryniarski
            <ul>
                <li>skontaktuj się</li>
                <li>poznaj naszą firmę</li>
            </ul>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (index.php)
  23. Krok 23: Zapytanie 1 jako zapytanie przygotowane

    Kryteria:

    R.5.3 Przynajmniej jedno zapytanie zostało wysłane do bazy: skrypt 1 - zapytanie 1 lub skrypt 2 - zapytanie 2 lub skrypt 3 - zapytanie 3 lub 4

    ok. 3 min
    Polecenie z arkusza

    Skrypt 1 wysyła do bazy zapytanie 1 i zwrócone zapytaniem dane wypisuje według schematu:

    Zapytanie 1 z kwerendy.txt z jedną zmianą: w miejscu liczby 2 stoi :id - nazwany parametr. prepare wysyła do bazy samą treść zapytania, execute(['id' => $id]) - wartość osobno, więc dane nigdy nie staną się kodem SQL (R.5.3). fetch() zwraca jeden wiersz albo false, gdy pracownika o tym numerze nie ma - dlatego $employee ma wartość początkową false także wtedy, gdy połączenie się nie udało.

    index.php PHP zmienione: 5 linii
    <?php
    $id = 2;
    $error = '';
    $employee = false;
    
    try {
        $pdo = new PDO('mysql:host=localhost;dbname=firma;charset=utf8mb4', 'root', '', [
            PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
            PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
        ]);
    
        $statement = $pdo->prepare('SELECT imie, nazwisko, adres, miasto, czyRODO, czyBadania FROM pracownicy WHERE id = :id');
        $statement->execute(['id' => $id]);
        $employee = $statement->fetch();
    } catch (PDOException $exception) {
        $error = 'Brak połączenia z bazą danych - spróbuj później.';
    } finally {
        $pdo = null;
    }
    ?>
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>Sekretariat</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <main>
            <section id="left">
                <h1>Akta Pracownicze</h1>
                <hr>
                <h3>Dokumenty pracownika</h3>
                <a href="cv.txt">Pobierz</a>
                <h1>Liczba zatrudnionych pracowników</h1>
                <p></p>
            </section>
            <section id="right">
            </section>
        </main>
        <footer>
            Autorem aplikacji jest: Bartosz Bryniarski
            <ul>
                <li>skontaktuj się</li>
                <li>poznaj naszą firmę</li>
            </ul>
        </footer>
    </body>
    </html>

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

  24. Krok 24: Skrypt 1: nagłówek „dane” i imię z nazwiskiem

    ok. 3 min
    Polecenie z arkusza

    Nagłówek trzeciego stopnia o treści „dane”. Paragraf z imieniem i nazwiskiem wybranymi z bazy

    W miejscu skryptu 1 zostaje samo wypisywanie:

    • <?php if ($employee): ?> … <?php endif; ?> - składnia alternatywna if z dwukropkiem; między znacznikami PHP stoi zwykły HTML, łatwiejszy do czytania niż echo z cudzysłowami. Gdy pracownika nie ma, cały fragment znika,
    • <?= … ?> - skrót od <?php echo … ?>,
    • e() - funkcja zdefiniowana na górze pliku: htmlspecialchars zamienia <, >, & i cudzysłowy na encje, więc nazwisko z kodem <script> w bazie wyświetli się jako tekst, a nie wykona.
    index.php PHP zmienione: 9 linii
    <?php
    $id = 2;
    $error = '';
    $employee = false;
    
    function e($value): string
    {
        return htmlspecialchars((string) $value);
    }
    
    try {
        $pdo = new PDO('mysql:host=localhost;dbname=firma;charset=utf8mb4', 'root', '', [
            PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
            PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
        ]);
    
        $statement = $pdo->prepare('SELECT imie, nazwisko, adres, miasto, czyRODO, czyBadania FROM pracownicy WHERE id = :id');
        $statement->execute(['id' => $id]);
        $employee = $statement->fetch();
    } catch (PDOException $exception) {
        $error = 'Brak połączenia z bazą danych - spróbuj później.';
    } finally {
        $pdo = null;
    }
    ?>
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>Sekretariat</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <main>
            <section id="left">
                <h1>Akta Pracownicze</h1>
                <?php if ($employee): ?>
                    <h3>dane</h3>
                    <p><?= e($employee['imie']) ?> <?= e($employee['nazwisko']) ?></p>
                <?php endif; ?>
                <hr>
                <h3>Dokumenty pracownika</h3>
                <a href="cv.txt">Pobierz</a>
                <h1>Liczba zatrudnionych pracowników</h1>
                <p></p>
            </section>
            <section id="right">
            </section>
        </main>
        <footer>
            Autorem aplikacji jest: Bartosz Bryniarski
            <ul>
                <li>skontaktuj się</li>
                <li>poznaj naszą firmę</li>
            </ul>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (index.php)
  25. Krok 25: Skrypt 1: linie i adres z miastem

    Kryteria:

    R.5.4 Skrypt 1 wyświetla w bloku lewym imię, nazwisko, adres i miasto oraz linie horyzontalne zgodne z obrazem 2 w arkuszu egzaminacyjnym

    ok. 2 min
    Polecenie z arkusza

    Linia horyzontalna. Nagłówek trzeciego stopnia o treści „adres”. Paragraf z adresem oraz paragraf z miastem wybranymi z bazy. Linia horyzontalna

    Dwie linie <hr>, nagłówek „adres” i dwa paragrafy z kolumn adres i miasto - nazwy kolumn zamiast numerów nie pomylą się po zmianie kolejności w SELECT (R.5.4).

    index.php PHP zmienione: 5 linii
    <?php
    $id = 2;
    $error = '';
    $employee = false;
    
    function e($value): string
    {
        return htmlspecialchars((string) $value);
    }
    
    try {
        $pdo = new PDO('mysql:host=localhost;dbname=firma;charset=utf8mb4', 'root', '', [
            PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
            PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
        ]);
    
        $statement = $pdo->prepare('SELECT imie, nazwisko, adres, miasto, czyRODO, czyBadania FROM pracownicy WHERE id = :id');
        $statement->execute(['id' => $id]);
        $employee = $statement->fetch();
    } catch (PDOException $exception) {
        $error = 'Brak połączenia z bazą danych - spróbuj później.';
    } finally {
        $pdo = null;
    }
    ?>
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>Sekretariat</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <main>
            <section id="left">
                <h1>Akta Pracownicze</h1>
                <?php if ($employee): ?>
                    <h3>dane</h3>
                    <p><?= e($employee['imie']) ?> <?= e($employee['nazwisko']) ?></p>
                    <hr>
                    <h3>adres</h3>
                    <p><?= e($employee['adres']) ?></p>
                    <p><?= e($employee['miasto']) ?></p>
                    <hr>
                <?php endif; ?>
                <hr>
                <h3>Dokumenty pracownika</h3>
                <a href="cv.txt">Pobierz</a>
                <h1>Liczba zatrudnionych pracowników</h1>
                <p></p>
            </section>
            <section id="right">
            </section>
        </main>
        <footer>
            Autorem aplikacji jest: Bartosz Bryniarski
            <ul>
                <li>skontaktuj się</li>
                <li>poznaj naszą firmę</li>
            </ul>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (index.php)
  26. Krok 26: Skrypt 1: status dokumentu RODO

    Kryteria:

    R.5.5 W skrypcie 1 zastosowano przynajmniej jedną instrukcję warunkową lub wyboru do sprawdzenia wartości zmiennej czyRODO lub czyBadania. Na stronie wyświetlony jest przynajmniej jeden komunikat zgodnie z wartością zmiennej logicznej

    ok. 2 min
    Polecenie z arkusza

    Paragraf o treści „RODO: podpisano” lub „RODO: niepodpisano” w zależności od wartości pola czyRODO zwróconego zapytaniem. Operacja musi mieć charakter uniwersalny niezależnie od wartości zwracanej kwerendą 1

    Instrukcja warunkowa if … else w składni alternatywnej wybiera jeden z dwóch paragrafów według pola czyRODO (R.5.5). Sprawdzone dla pracownika o id 3 (Katarzyna Kowalska): „RODO: niepodpisano”.

    index.php PHP zmienione: 5 linii
    <?php
    $id = 2;
    $error = '';
    $employee = false;
    
    function e($value): string
    {
        return htmlspecialchars((string) $value);
    }
    
    try {
        $pdo = new PDO('mysql:host=localhost;dbname=firma;charset=utf8mb4', 'root', '', [
            PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
            PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
        ]);
    
        $statement = $pdo->prepare('SELECT imie, nazwisko, adres, miasto, czyRODO, czyBadania FROM pracownicy WHERE id = :id');
        $statement->execute(['id' => $id]);
        $employee = $statement->fetch();
    } catch (PDOException $exception) {
        $error = 'Brak połączenia z bazą danych - spróbuj później.';
    } finally {
        $pdo = null;
    }
    ?>
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>Sekretariat</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <main>
            <section id="left">
                <h1>Akta Pracownicze</h1>
                <?php if ($employee): ?>
                    <h3>dane</h3>
                    <p><?= e($employee['imie']) ?> <?= e($employee['nazwisko']) ?></p>
                    <hr>
                    <h3>adres</h3>
                    <p><?= e($employee['adres']) ?></p>
                    <p><?= e($employee['miasto']) ?></p>
                    <hr>
                    <?php if ($employee['czyRODO'] == 1): ?>
                        <p>RODO: podpisano</p>
                    <?php else: ?>
                        <p>RODO: niepodpisano</p>
                    <?php endif; ?>
                <?php endif; ?>
                <hr>
                <h3>Dokumenty pracownika</h3>
                <a href="cv.txt">Pobierz</a>
                <h1>Liczba zatrudnionych pracowników</h1>
                <p></p>
            </section>
            <section id="right">
            </section>
        </main>
        <footer>
            Autorem aplikacji jest: Bartosz Bryniarski
            <ul>
                <li>skontaktuj się</li>
                <li>poznaj naszą firmę</li>
            </ul>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (index.php)
  27. Krok 27: Skrypt 1: status badań pracowniczych

    ok. 2 min
    Polecenie z arkusza

    Paragraf o treści „Badania: aktualne” lub „Badania: nieaktualne” w zależności od wartości pola czyBadania zwróconego zapytaniem. Operacja musi mieć charakter uniwersalny niezależnie od wartości zwracanej kwerendą 1

    To samo dla czyBadania. Sprawdzone dla id 4 (Ewelina Rak): „Badania: nieaktualne”.

    index.php PHP zmienione: 5 linii
    <?php
    $id = 2;
    $error = '';
    $employee = false;
    
    function e($value): string
    {
        return htmlspecialchars((string) $value);
    }
    
    try {
        $pdo = new PDO('mysql:host=localhost;dbname=firma;charset=utf8mb4', 'root', '', [
            PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
            PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
        ]);
    
        $statement = $pdo->prepare('SELECT imie, nazwisko, adres, miasto, czyRODO, czyBadania FROM pracownicy WHERE id = :id');
        $statement->execute(['id' => $id]);
        $employee = $statement->fetch();
    } catch (PDOException $exception) {
        $error = 'Brak połączenia z bazą danych - spróbuj później.';
    } finally {
        $pdo = null;
    }
    ?>
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>Sekretariat</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <main>
            <section id="left">
                <h1>Akta Pracownicze</h1>
                <?php if ($employee): ?>
                    <h3>dane</h3>
                    <p><?= e($employee['imie']) ?> <?= e($employee['nazwisko']) ?></p>
                    <hr>
                    <h3>adres</h3>
                    <p><?= e($employee['adres']) ?></p>
                    <p><?= e($employee['miasto']) ?></p>
                    <hr>
                    <?php if ($employee['czyRODO'] == 1): ?>
                        <p>RODO: podpisano</p>
                    <?php else: ?>
                        <p>RODO: niepodpisano</p>
                    <?php endif; ?>
                    <?php if ($employee['czyBadania'] == 1): ?>
                        <p>Badania: aktualne</p>
                    <?php else: ?>
                        <p>Badania: nieaktualne</p>
                    <?php endif; ?>
                <?php endif; ?>
                <hr>
                <h3>Dokumenty pracownika</h3>
                <a href="cv.txt">Pobierz</a>
                <h1>Liczba zatrudnionych pracowników</h1>
                <p></p>
            </section>
            <section id="right">
            </section>
        </main>
        <footer>
            Autorem aplikacji jest: Bartosz Bryniarski
            <ul>
                <li>skontaktuj się</li>
                <li>poznaj naszą firmę</li>
            </ul>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (index.php)
  28. Krok 28: Skrypt 2: liczba pracowników

    Kryteria:

    R.5.6 Skrypt 2 wyświetla wartość zwróconą zapytaniem 2

    ok. 2 min
    Polecenie z arkusza

    Skrypt 2 wysyła do bazy zapytanie 2 i wypisuje liczbę wybraną zapytaniem

    Zapytanie 2 nie ma żadnych danych z zewnątrz, więc wystarczy query. fetchColumn() zwraca od razu pierwszą kolumnę pierwszego wiersza - liczbę 9. W paragrafie zostaje jedna linia wypisująca $count (R.5.6).

    index.php PHP zmienione: 4 linie
    <?php
    $id = 2;
    $error = '';
    $employee = false;
    $count = 0;
    
    function e($value): string
    {
        return htmlspecialchars((string) $value);
    }
    
    try {
        $pdo = new PDO('mysql:host=localhost;dbname=firma;charset=utf8mb4', 'root', '', [
            PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
            PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
        ]);
    
        $statement = $pdo->prepare('SELECT imie, nazwisko, adres, miasto, czyRODO, czyBadania FROM pracownicy WHERE id = :id');
        $statement->execute(['id' => $id]);
        $employee = $statement->fetch();
    
        $count = $pdo->query('SELECT COUNT(*) FROM pracownicy')->fetchColumn();
    } catch (PDOException $exception) {
        $error = 'Brak połączenia z bazą danych - spróbuj później.';
    } finally {
        $pdo = null;
    }
    ?>
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>Sekretariat</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <main>
            <section id="left">
                <h1>Akta Pracownicze</h1>
                <?php if ($employee): ?>
                    <h3>dane</h3>
                    <p><?= e($employee['imie']) ?> <?= e($employee['nazwisko']) ?></p>
                    <hr>
                    <h3>adres</h3>
                    <p><?= e($employee['adres']) ?></p>
                    <p><?= e($employee['miasto']) ?></p>
                    <hr>
                    <?php if ($employee['czyRODO'] == 1): ?>
                        <p>RODO: podpisano</p>
                    <?php else: ?>
                        <p>RODO: niepodpisano</p>
                    <?php endif; ?>
                    <?php if ($employee['czyBadania'] == 1): ?>
                        <p>Badania: aktualne</p>
                    <?php else: ?>
                        <p>Badania: nieaktualne</p>
                    <?php endif; ?>
                <?php endif; ?>
                <hr>
                <h3>Dokumenty pracownika</h3>
                <a href="cv.txt">Pobierz</a>
                <h1>Liczba zatrudnionych pracowników</h1>
                <p><?= e($count) ?></p>
            </section>
            <section id="right">
            </section>
        </main>
        <footer>
            Autorem aplikacji jest: Bartosz Bryniarski
            <ul>
                <li>skontaktuj się</li>
                <li>poznaj naszą firmę</li>
            </ul>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (index.php)
  29. Krok 29: Skrypt 3: zapytanie 3 i zdjęcie o nazwie z id

    Kryteria: ,

    R.2.8 W bloku prawym umieszczono obraz z tekstem alternatywnym "pracownik" (w skrypcie lub HTML)

    R.5.7 W skrypcie 3 ustalono nazwę pliku na podstawie wartości id zwróconej zapytaniem np. $wiersz[0] = (string) $wiersz[0] . ".jpg"; oraz wyświetlono obraz z pliku o tej nazwie

    ok. 3 min
    Polecenie z arkusza

    Zawartość bloku prawego: efekt działania skryptu 3. Skrypt 3 wysyła do bazy zapytanie 3 a następnie: Ustala nazwę pliku obrazu według schematu: „<id>.jpg” gdzie <id> oznacza id zwrócone zapytaniem, a operacja ma charakter uniwersalny niezależnie od zwróconej wartości. Wyświetla obraz o ustalonej nazwie pliku z tekstem alternatywnym o treści „pracownik”

    Zapytanie 3 przygotowane tak samo jak zapytanie 1, wynik w $person. Nazwa pliku powstaje w atrybucie src: $person['id'] . '.jpg' - id z bazy sklejone kropką z rozszerzeniem, czyli 2.jpg (R.5.7). Znacznik <img> z alt="pracownik" jest w HTML-u, a e() chroni atrybut przed cudzysłowem z danych (R.2.8).

    index.php PHP zmienione: 8 linii
    <?php
    $id = 2;
    $error = '';
    $employee = false;
    $count = 0;
    $person = false;
    
    function e($value): string
    {
        return htmlspecialchars((string) $value);
    }
    
    try {
        $pdo = new PDO('mysql:host=localhost;dbname=firma;charset=utf8mb4', 'root', '', [
            PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
            PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
        ]);
    
        $statement = $pdo->prepare('SELECT imie, nazwisko, adres, miasto, czyRODO, czyBadania FROM pracownicy WHERE id = :id');
        $statement->execute(['id' => $id]);
        $employee = $statement->fetch();
    
        $count = $pdo->query('SELECT COUNT(*) FROM pracownicy')->fetchColumn();
    
        $statement = $pdo->prepare('SELECT id, imie, nazwisko FROM pracownicy WHERE id = :id');
        $statement->execute(['id' => $id]);
        $person = $statement->fetch();
    } catch (PDOException $exception) {
        $error = 'Brak połączenia z bazą danych - spróbuj później.';
    } finally {
        $pdo = null;
    }
    ?>
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>Sekretariat</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <main>
            <section id="left">
                <h1>Akta Pracownicze</h1>
                <?php if ($employee): ?>
                    <h3>dane</h3>
                    <p><?= e($employee['imie']) ?> <?= e($employee['nazwisko']) ?></p>
                    <hr>
                    <h3>adres</h3>
                    <p><?= e($employee['adres']) ?></p>
                    <p><?= e($employee['miasto']) ?></p>
                    <hr>
                    <?php if ($employee['czyRODO'] == 1): ?>
                        <p>RODO: podpisano</p>
                    <?php else: ?>
                        <p>RODO: niepodpisano</p>
                    <?php endif; ?>
                    <?php if ($employee['czyBadania'] == 1): ?>
                        <p>Badania: aktualne</p>
                    <?php else: ?>
                        <p>Badania: nieaktualne</p>
                    <?php endif; ?>
                <?php endif; ?>
                <hr>
                <h3>Dokumenty pracownika</h3>
                <a href="cv.txt">Pobierz</a>
                <h1>Liczba zatrudnionych pracowników</h1>
                <p><?= e($count) ?></p>
            </section>
            <section id="right">
                <?php if ($person): ?>
                    <img src="<?= e($person['id'] . '.jpg') ?>" alt="pracownik">
                <?php endif; ?>
            </section>
        </main>
        <footer>
            Autorem aplikacji jest: Bartosz Bryniarski
            <ul>
                <li>skontaktuj się</li>
                <li>poznaj naszą firmę</li>
            </ul>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (index.php)
  30. Krok 30: Skrypt 3: imię i nazwisko w nagłówku

    Kryteria:

    R.5.8 Skrypt 3 wyświetla imię i nazwisko zwrócone zapytaniem

    ok. 1 min
    Polecenie z arkusza

    Wyświetla w nagłówku drugiego stopnia imię i nazwisko zwrócone zapytaniem

    <h2> z kolumnami imie i nazwisko z zapytania 3 (R.5.8).

    index.php PHP zmienione: 1 linia
    <?php
    $id = 2;
    $error = '';
    $employee = false;
    $count = 0;
    $person = false;
    
    function e($value): string
    {
        return htmlspecialchars((string) $value);
    }
    
    try {
        $pdo = new PDO('mysql:host=localhost;dbname=firma;charset=utf8mb4', 'root', '', [
            PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
            PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
        ]);
    
        $statement = $pdo->prepare('SELECT imie, nazwisko, adres, miasto, czyRODO, czyBadania FROM pracownicy WHERE id = :id');
        $statement->execute(['id' => $id]);
        $employee = $statement->fetch();
    
        $count = $pdo->query('SELECT COUNT(*) FROM pracownicy')->fetchColumn();
    
        $statement = $pdo->prepare('SELECT id, imie, nazwisko FROM pracownicy WHERE id = :id');
        $statement->execute(['id' => $id]);
        $person = $statement->fetch();
    } catch (PDOException $exception) {
        $error = 'Brak połączenia z bazą danych - spróbuj później.';
    } finally {
        $pdo = null;
    }
    ?>
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>Sekretariat</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <main>
            <section id="left">
                <h1>Akta Pracownicze</h1>
                <?php if ($employee): ?>
                    <h3>dane</h3>
                    <p><?= e($employee['imie']) ?> <?= e($employee['nazwisko']) ?></p>
                    <hr>
                    <h3>adres</h3>
                    <p><?= e($employee['adres']) ?></p>
                    <p><?= e($employee['miasto']) ?></p>
                    <hr>
                    <?php if ($employee['czyRODO'] == 1): ?>
                        <p>RODO: podpisano</p>
                    <?php else: ?>
                        <p>RODO: niepodpisano</p>
                    <?php endif; ?>
                    <?php if ($employee['czyBadania'] == 1): ?>
                        <p>Badania: aktualne</p>
                    <?php else: ?>
                        <p>Badania: nieaktualne</p>
                    <?php endif; ?>
                <?php endif; ?>
                <hr>
                <h3>Dokumenty pracownika</h3>
                <a href="cv.txt">Pobierz</a>
                <h1>Liczba zatrudnionych pracowników</h1>
                <p><?= e($count) ?></p>
            </section>
            <section id="right">
                <?php if ($person): ?>
                    <img src="<?= e($person['id'] . '.jpg') ?>" alt="pracownik">
                    <h2><?= e($person['imie']) ?> <?= e($person['nazwisko']) ?></h2>
                <?php endif; ?>
            </section>
        </main>
        <footer>
            Autorem aplikacji jest: Bartosz Bryniarski
            <ul>
                <li>skontaktuj się</li>
                <li>poznaj naszą firmę</li>
            </ul>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (index.php)
  31. Krok 31: Skrypt 3: zapytanie 4, nazwa i opis stanowiska

    Kryteria: ,

    R.2.6 W bloku lewym zapisano: jeden z nagłówków h1: "Akta Pracownicze" lub "Liczba zatrudnionych pracowników"; przynajmniej jeden nagłówek h3: "dane", "adres", "Dokumenty pracownika" (w skrypcie lub HTML) oraz przynajmniej jeden paragraf. W bloku prawym zapisano nagłówki h2, h4, h5 (w skrypcie lub HTML)

    R.5.9 Skrypt 3 wyświetla nazwę stanowiska oraz opis stanowiska zwrócone zapytaniem

    ok. 3 min
    Polecenie z arkusza

    Wysyła do bazy zapytanie 4. Wyświetla nazwę stanowiska w nagłówku czwartego stopnia. Wyświetla opis stanowiska w nagłówku piątego stopnia

    Zapytanie 4 jako czwarte w bloku try - nadal przed finally, więc zamknięcie połączenia zostaje ostatnią operacją na bazie. W bloku prawym <h4> z nazwą i <h5> z opisem stanowiska (R.5.9). Komplet nagłówków w obu blokach jest na stronie (R.2.6).

    index.php PHP zmienione: 9 linii
    <?php
    $id = 2;
    $error = '';
    $employee = false;
    $count = 0;
    $person = false;
    $position = false;
    
    function e($value): string
    {
        return htmlspecialchars((string) $value);
    }
    
    try {
        $pdo = new PDO('mysql:host=localhost;dbname=firma;charset=utf8mb4', 'root', '', [
            PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
            PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
        ]);
    
        $statement = $pdo->prepare('SELECT imie, nazwisko, adres, miasto, czyRODO, czyBadania FROM pracownicy WHERE id = :id');
        $statement->execute(['id' => $id]);
        $employee = $statement->fetch();
    
        $count = $pdo->query('SELECT COUNT(*) FROM pracownicy')->fetchColumn();
    
        $statement = $pdo->prepare('SELECT id, imie, nazwisko FROM pracownicy WHERE id = :id');
        $statement->execute(['id' => $id]);
        $person = $statement->fetch();
    
        $statement = $pdo->prepare('SELECT pracownicy.id, nazwa, opis FROM pracownicy JOIN stanowiska ON pracownicy.stanowiska_id = stanowiska.id WHERE pracownicy.id = :id');
        $statement->execute(['id' => $id]);
        $position = $statement->fetch();
    } catch (PDOException $exception) {
        $error = 'Brak połączenia z bazą danych - spróbuj później.';
    } finally {
        $pdo = null;
    }
    ?>
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>Sekretariat</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <main>
            <section id="left">
                <h1>Akta Pracownicze</h1>
                <?php if ($employee): ?>
                    <h3>dane</h3>
                    <p><?= e($employee['imie']) ?> <?= e($employee['nazwisko']) ?></p>
                    <hr>
                    <h3>adres</h3>
                    <p><?= e($employee['adres']) ?></p>
                    <p><?= e($employee['miasto']) ?></p>
                    <hr>
                    <?php if ($employee['czyRODO'] == 1): ?>
                        <p>RODO: podpisano</p>
                    <?php else: ?>
                        <p>RODO: niepodpisano</p>
                    <?php endif; ?>
                    <?php if ($employee['czyBadania'] == 1): ?>
                        <p>Badania: aktualne</p>
                    <?php else: ?>
                        <p>Badania: nieaktualne</p>
                    <?php endif; ?>
                <?php endif; ?>
                <hr>
                <h3>Dokumenty pracownika</h3>
                <a href="cv.txt">Pobierz</a>
                <h1>Liczba zatrudnionych pracowników</h1>
                <p><?= e($count) ?></p>
            </section>
            <section id="right">
                <?php if ($person): ?>
                    <img src="<?= e($person['id'] . '.jpg') ?>" alt="pracownik">
                    <h2><?= e($person['imie']) ?> <?= e($person['nazwisko']) ?></h2>
                <?php endif; ?>
                <?php if ($position): ?>
                    <h4><?= e($position['nazwa']) ?></h4>
                    <h5><?= e($position['opis']) ?></h5>
                <?php endif; ?>
            </section>
        </main>
        <footer>
            Autorem aplikacji jest: Bartosz Bryniarski
            <ul>
                <li>skontaktuj się</li>
                <li>poznaj naszą firmę</li>
            </ul>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (index.php)
  32. Krok 32: Komunikat, gdy baza nie działa

    ok. 2 min
    Polecenie z arkusza

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

    Gdy połączenie się nie uda, catch zapisał komunikat w $error - teraz strona go wypisuje pod nagłówkiem. Sprawdzone ze złą nazwą bazy: zamiast „Fatal error: Uncaught PDOException: SQLSTATE[HY000] [1049] Unknown database…” ze ścieżką pliku strona pokazuje jedno zdanie, a reszta - nagłówki, odnośnik, stopka - działa. Przy poprawnej bazie podgląd się nie zmienia.

    index.php PHP zmienione: 3 linie
    <?php
    $id = 2;
    $error = '';
    $employee = false;
    $count = 0;
    $person = false;
    $position = false;
    
    function e($value): string
    {
        return htmlspecialchars((string) $value);
    }
    
    try {
        $pdo = new PDO('mysql:host=localhost;dbname=firma;charset=utf8mb4', 'root', '', [
            PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
            PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
        ]);
    
        $statement = $pdo->prepare('SELECT imie, nazwisko, adres, miasto, czyRODO, czyBadania FROM pracownicy WHERE id = :id');
        $statement->execute(['id' => $id]);
        $employee = $statement->fetch();
    
        $count = $pdo->query('SELECT COUNT(*) FROM pracownicy')->fetchColumn();
    
        $statement = $pdo->prepare('SELECT id, imie, nazwisko FROM pracownicy WHERE id = :id');
        $statement->execute(['id' => $id]);
        $person = $statement->fetch();
    
        $statement = $pdo->prepare('SELECT pracownicy.id, nazwa, opis FROM pracownicy JOIN stanowiska ON pracownicy.stanowiska_id = stanowiska.id WHERE pracownicy.id = :id');
        $statement->execute(['id' => $id]);
        $position = $statement->fetch();
    } catch (PDOException $exception) {
        $error = 'Brak połączenia z bazą danych - spróbuj później.';
    } finally {
        $pdo = null;
    }
    ?>
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>Sekretariat</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <main>
            <section id="left">
                <h1>Akta Pracownicze</h1>
                <?php if ($error): ?>
                    <p><?= e($error) ?></p>
                <?php endif; ?>
                <?php if ($employee): ?>
                    <h3>dane</h3>
                    <p><?= e($employee['imie']) ?> <?= e($employee['nazwisko']) ?></p>
                    <hr>
                    <h3>adres</h3>
                    <p><?= e($employee['adres']) ?></p>
                    <p><?= e($employee['miasto']) ?></p>
                    <hr>
                    <?php if ($employee['czyRODO'] == 1): ?>
                        <p>RODO: podpisano</p>
                    <?php else: ?>
                        <p>RODO: niepodpisano</p>
                    <?php endif; ?>
                    <?php if ($employee['czyBadania'] == 1): ?>
                        <p>Badania: aktualne</p>
                    <?php else: ?>
                        <p>Badania: nieaktualne</p>
                    <?php endif; ?>
                <?php endif; ?>
                <hr>
                <h3>Dokumenty pracownika</h3>
                <a href="cv.txt">Pobierz</a>
                <h1>Liczba zatrudnionych pracowników</h1>
                <p><?= e($count) ?></p>
            </section>
            <section id="right">
                <?php if ($person): ?>
                    <img src="<?= e($person['id'] . '.jpg') ?>" alt="pracownik">
                    <h2><?= e($person['imie']) ?> <?= e($person['nazwisko']) ?></h2>
                <?php endif; ?>
                <?php if ($position): ?>
                    <h4><?= e($position['nazwa']) ?></h4>
                    <h5><?= e($position['opis']) ?></h5>
                <?php endif; ?>
            </section>
        </main>
        <footer>
            Autorem aplikacji jest: Bartosz Bryniarski
            <ul>
                <li>skontaktuj się</li>
                <li>poznaj naszą firmę</li>
            </ul>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (index.php)
  33. Etap 5: Porównanie z wersją podstawową

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

    Krok 33: Co jest inaczej i którą wersję wybrać na egzaminie

    ok. 3 min

    Obie wersje dają komplet 37 punktów. Różnice:

    wersja podstawowawersja nowoczesna
    układfloat: left sekcji, clear stopki<main> z grid-template-columns: 50% 30%
    szerokość bloku50% plus margines na zewnątrz50% razem z marginesem (o 40 px węższy)
    bibliotekamysqli (tabela 1 arkusza)PDO z wyjątkami
    gdzie jest skrypttrzy bloki PHP między HTML-emzapytania na górze pliku, w HTML-u tylko wypisywanie
    warunek id = 2wpisany w treść zapytaniaparametr :id w zapytaniu przygotowanym
    wiersz wyniku$row[0], $row[1]…$employee['imie'], $employee['nazwisko']…
    dane z bazyecho wproste() = htmlspecialchars
    zamknięcie bazymysqli_close na końcu skryptu 3$pdo = null w finally
    baza nie działa„Fatal error” ze ścieżką plikukomunikat na stronie

    Na egzaminie wersja podstawowa trzyma się funkcji z tabeli 1 i łatwiej ją napisać bez dokumentacji; skrypty stoją dokładnie tam, gdzie arkusz każe pokazać ich efekt. Nowoczesna oddziela pobieranie danych od ich wyświetlania, nie wykonuje kodu zapisanego w bazie i jest gotowa na numer pracownika z adresu strony - a klucz przyjmuje obie.

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

  34. Etap 6: Oddanie pracy

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

    Krok 34: Nagranie płyty

    ok. 5 min
    Polecenie z arkusza

    UWAGA: katalog z rezultatami pracy oraz płytę należy opisać numerem, którym został podpisany arkusz, czyli numerem PESEL lub w przypadku jego braku numerem paszportu.

    W folderze z numerem zdającego: 2.jpg, cv.txt, import.jpg, kw1.png - kw4.png, kwerendy.txt, index.php i styl.css. Nagraj płytę, sprawdź jej odczyt i opisz ją numerem zdającego.

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

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