Przejdź do głównej treści
E.14-02-21.06-SGCzerwiec 2021 · 45 kroków · ok. 81 min · 39 kryteriów z klucza

Rozwiązanie krok po kroku: Hurtownia artykułów biurowych i kalkulator zakupów (Wersja podstawowa)

Strona hurtowni artykułów biurowych: import gotowej bazy sklep z pliku sklep.sql, cztery zapytania - nazwy i ceny czterech pierwszych towarów (LIMIT), cena cyrkla, nazwy wszystkich towarów i liczba towarów w promocji i poza nią (COUNT z GROUP BY) - oraz grafika przeskalowana do szerokości 150 px z zachowaniem przezroczystości. Strona index.php ma baner, trzy panele i stopkę, style w styl.css i dwa skrypty PHP: pierwszy wypisuje cennik w tabeli, drugi liczy wartość zakupów - cenę wybranego artykułu razy liczbę sztuk.

To arkusz E.14 z czerwca 2021 - kwalifikacji formuły 2012, którą zastąpiła INF.03. Jest pokrewny zadaniu E.14-01-21.06 z tej samej sesji (ta sama baza sklep, inna grafika, układ i skrypty). Kroki idą zdanie po zdaniu za treścią arkusza - przy każdym jest polecenie z arkusza, a kod pokazuje dokładnie te linie, które je spełniają. Skrypty są najpierw napisane najprościej, funkcjami mysqli z tabeli 1 arkusza, a na końcu sprawdzone na prawdziwych nietypowych danych z formularza i zabezpieczone.

To jest wersja podstawowa. W zakładce „Nowoczesny kod (flex, PDO)” jest drugi sposób rozwiązania tego samego arkusza: układ na flex we wspólnym pojemniku, semantyczne znaczniki, PDO z zapytaniem przygotowanym, sprawdzona liczba sztuk i zabezpieczone wypisywanie danych - obie wersje są zgodne z kluczem.

Materiały. Archiwum pliki2.zip z arkusza nie zachowało się w publicznych źródłach. Pliki sklep.sql i zakupy.png pochodzą z oryginalnego archiwum CKE do zadania E.14-02-19.06 - mają te same nazwy, struktura bazy jest identyczna z obrazem 1 tego arkusza, a zapytania z klucza dają na nich dokładnie wyniki podane w kluczu. Archiwum odtworzone z tych plików (hasło jak w arkuszu) jest do pobrania na stronie arkusza. Zapytania wykonano na MariaDB 10.4 - tej samej, która jest w XAMPP. Podgląd od kroków z PHP to wynik prawdziwego uruchomienia kodu w PHP 8.2.

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-7 · po tym etapie masz 6 z 39 kryteriów (pkt)

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

    ok. 2 min
    Polecenie z arkusza

    Aby wykonać zadanie, zaloguj się na konto Egzamin bez hasła. Na pulpicie znajdziesz archiwum ZIP o nazwie pliki2.zip zabezpieczone hasłem: Zad@n!E_14 Archiwum należy rozpakować. Na pulpicie konta Egzamin utwórz folder. Jako nazwy folderu użyj swojego numeru PESEL. Rozpakowane pliki umieść w tym folderze. Wyniki swojej pracy również zapisz w tym folderze.

    Na pulpicie tworzysz folder nazwany numerem PESEL - w tym rozwiązaniu w jego miejscu stoi imię i nazwisko autora, Bartosz Bryniarski. Archiwum pliki2.zip otwierasz programem 7-Zip i rozpakowujesz do tego folderu z hasłem Zad@n!E_14 - wielkość liter i znaki @, !, _ mają znaczenie. W środku są dwa pliki: sklep.sql (tabele do zaimportowania) i zakupy.png (grafika do przeskalowania).

    Typowe błędy

    Pliki zapisane poza folderem zdającego nie trafią na płytę - a ocenia się wyłącznie to, co jest na płycie.

    sklep.sql SQL nowy plik
    -- phpMyAdmin SQL Dump
    -- version 4.5.1
    -- http://www.phpmyadmin.net
    --
    -- Host: 127.0.0.1
    -- Czas generowania: 14 Lis 2017, 11:08
    -- Wersja serwera: 10.1.10-MariaDB
    -- Wersja PHP: 5.6.15
    
    SET SQL_MODE = "NO_AUTO_VALUE_ON_ZERO";
    SET time_zone = "+00:00";
    
    
    /*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
    /*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
    /*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
    /*!40101 SET NAMES utf8mb4 */;
    
    --
    -- Baza danych: `sklep2`
    --
    
    -- --------------------------------------------------------
    
    --
    -- Struktura tabeli dla tabeli `dostawcy`
    --
    
    CREATE TABLE `dostawcy` (
      `id` int(11) NOT NULL,
      `nazwa` varchar(50) NOT NULL,
      `adres` varchar(50) NOT NULL
    ) ENGINE=InnoDB DEFAULT CHARSET=latin1;
    
    --
    -- Zrzut danych tabeli `dostawcy`
    --
    
    INSERT INTO `dostawcy` (`id`, `nazwa`, `adres`) VALUES
    (1, 'Papiernictwo', 'ul. Boczna 12, 23-355 Bukowina'),
    (2, 'Art. szkolne', 'ul. Dworcowa 20, 34-565 Warszawa'),
    (3, 'Wszystko dla ucznia', 'ul. Towarowa 35, 88-123 Zakopane');
    
    -- --------------------------------------------------------
    
    --
    -- Struktura tabeli dla tabeli `towary`
    --
    
    CREATE TABLE `towary` (
      `id` int(11) NOT NULL,
      `nazwa` varchar(20) NOT NULL,
      `cena` float NOT NULL,
      `promocja` tinyint(1) NOT NULL,
      `idDostawcy` int(11) NOT NULL
    ) ENGINE=InnoDB DEFAULT CHARSET=latin1;
    
    --
    -- Zrzut danych tabeli `towary`
    --
    
    INSERT INTO `towary` (`id`, `nazwa`, `cena`, `promocja`, `idDostawcy`) VALUES
    (1, 'Zeszyt 60 kartek', 4.5, 0, 1),
    (2, 'Zeszyt 32 kartki', 1.2, 0, 2),
    (3, 'Cyrkiel', 12.4, 0, 1),
    (4, 'Linijka 30 cm', 7.2, 0, 3),
    (5, 'Ekierka', 5.5, 0, 3),
    (6, 'Linijka 50 cm', 8.2, 0, 2),
    (7, 'Gumka do mazania', 3.2, 1, 1),
    (8, 'Cienkopis', 2.5, 1, 2),
    (9, 'Pisaki 60 szt.', 55, 1, 2),
    (10, 'Markery 4 szt.', 22.4, 1, 1);
    
    --
    -- Indeksy dla zrzutów tabel
    --
    
    --
    -- Indexes for table `dostawcy`
    --
    ALTER TABLE `dostawcy`
      ADD PRIMARY KEY (`id`);
    
    --
    -- Indexes for table `towary`
    --
    ALTER TABLE `towary`
      ADD PRIMARY KEY (`id`);
    
    --
    -- AUTO_INCREMENT for dumped tables
    --
    
    --
    -- AUTO_INCREMENT dla tabeli `dostawcy`
    --
    ALTER TABLE `dostawcy`
      MODIFY `id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=4;
    --
    -- AUTO_INCREMENT dla tabeli `towary`
    --
    ALTER TABLE `towary`
      MODIFY `id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=11;
    /*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
    /*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
    /*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
  2. Krok 2: XAMPP i nowa baza sklep

    ok. 2 min
    Polecenie z arkusza

    Uruchom usługi MySQL i Apache z XAMPP Control Panel i przejdź do narzędzia phpMyAdmin. Następnie wykonaj operacje na bazie danych: Utwórz nową bazę danych o nazwie sklep

    W XAMPP Control Panel Start przy Apache i MySQL, potem http://localhost/phpmyadmin. W lewym panelu Nowa, nazwa bazy sklep, Utwórz. Porównywania napisów nie trzeba ustawiać - tabele z pliku mają własne kodowanie.

    Typowe błędy

    Komentarz w pliku sklep.sql wspomina bazę sklep2 - to tylko opis, z którego eksportowano tabele. Importujesz do bazy sklep, bo z nią łączy się skrypt (R.5.2).

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

    Kryteria:

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

    ok. 3 min
    Polecenie z arkusza

    Do bazy zaimportuj tabele z pliku sklep.sql, z wcześniej rozpakowanego archiwum. Wykonaj zrzut ekranu po imporcie. Zrzut zapisz w folderze z Twoim numerem PESEL, 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

    Zaznacz bazę sklep, karta Import, Wybierz plik - sklep.sql, Wykonaj. Powstają tabele z obrazu 1: towary (10 wierszy) i dostawcy (3 wiersze).

    Zielony komunikat o sukcesie i obie tabele w lewym panelu to „elementy wskazujące na poprawnie wykonany import”. Print Screen, wklejenie do edytora grafiki i zapis jako import.jpg (R.1.1) - w tym arkuszu zrzut nazywa się import, nie baza.

    Typowe błędy

    Zrzut ma być w JPEG, mieć nazwę import i obejmować cały ekran z paskiem zadań - wykadrowanego zrzutu egzaminator nie ocenia.

    Podgląd strony po tym kroku
    Podgląd strony po kroku 3
  4. Krok 4: Zapytanie 1: cztery pierwsze towary

    Kryteria: ,

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

    R.1.3 Zapisano zapytanie 1 wybierające jedynie pola nazwa i cena dla czterech pierwszych rekordów w tabeli towary. W pliku z kwerendami lub na zrzucie istnieje zapis np.: SELECT nazwa, cena FROM towary LIMIT 4; oraz na zrzucie widoczne są jedynie nazwy i ceny 4 produktów: Zeszyt 60 kartek - 4.5, Zeszyt 32 kartki - 1.2, Cyrkiel - 12.4, Linijka 30 cm - 7.2 (w zapytaniu zamiast klauzuli LIMIT można zastosować również WHERE określającą wartości w polu id, np.: id<=4, lub id=1 OR id=2 OR...)

    ok. 3 min
    Polecenie z arkusza

    Zapisz i wykonaj w phpMyAdmin podane niżej zapytania SQL działające na bazie danych. Wykonaj zrzuty ekranu przedstawiające wyniki działania zapytań. Zrzuty zapisz w formacie JPEG i nadaj im nazwy kw1, kw2, kw3, kw4. Zrzuty powinny obejmować cały ekran monitora z widocznym paskiem zadań oraz zawierać wynik działania zapytania. Zapytania zapisz w pliku kwerendy.txt. Pliki zawierające zrzuty ekranu oraz plik kwerendy.txt umieść w folderze z Twoim numerem PESEL. Zapytanie 1: wybierające jedynie pola nazwa i cena dla czterech pierwszych rekordów w tabeli towary

    Karta SQL bazy sklep:

    • SELECT nazwa, cena - dwa pola, bez *,
    • FROM towary,
    • LIMIT 4 - tylko cztery pierwsze wiersze wyniku.

    Wynik: Zeszyt 60 kartek 4.5, Zeszyt 32 kartki 1.2, Cyrkiel 12.4, Linijka 30 cm 7.2 (R.1.3). Zapytanie kopiujesz do nowego pliku kwerendy.txt (R.1.2), zrzut zapisujesz jako kw1.jpg. To zapytanie wykona skrypt 1.

    Typowe błędy

    Bez ORDER BY „pierwsze” znaczy kolejne w kolejności, w jakiej baza odda wiersze - tu jest to kolejność id. Klucz dopuszcza też warunek WHERE id <= 4.

    kwerendy.txt Tekst nowy plik
    -- Zapytanie 1
    SELECT nazwa, cena FROM towary LIMIT 4;
    Podgląd strony po tym kroku
    Podgląd strony po kroku 4
  5. Krok 5: Zapytanie 2: cena cyrkla

    Kryteria:

    R.1.4 Zapisano zapytanie 2 wybierające jedynie pole cena dla produktu cyrkiel. W pliku z kwerendami lub na zrzucie istnieje zapis np.: SELECT cena FROM towary WHERE nazwa='cyrkiel'; (alternatywnie id) oraz na zrzucie widoczna jest jedynie cena 12.4

    ok. 2 min
    Polecenie z arkusza

    Zapytanie 2: wybierające jedynie pole cena dla produktu cyrkiel z tabeli towary

    • SELECT cena FROM towary,
    • WHERE nazwa = 'Cyrkiel' - napis w apostrofach; porównywanie w tabeli latin1_swedish_ci nie rozróżnia wielkości liter, więc 'cyrkiel' też zadziała.

    Wynik: 12.4 (R.1.4). Zrzut: kw2.jpg. W skrypcie 2 w miejscu 'Cyrkiel' stanie artykuł wybrany w formularzu.

    kwerendy.txt Tekst zmienione: 3 linie
    -- Zapytanie 1
    SELECT nazwa, cena FROM towary LIMIT 4;
    
    -- Zapytanie 2
    SELECT cena FROM towary WHERE nazwa = 'Cyrkiel';
    Podgląd strony po tym kroku
    Podgląd strony po kroku 5
  6. Krok 6: Zapytanie 3: nazwy wszystkich towarów

    Kryteria:

    R.1.5 Zapisano zapytanie 3 wybierające jedynie pole nazwa dla wszystkich rekordów w tabeli towary. W pliku z kwerendami lub na zrzucie istnieje zapis np.: SELECT nazwa FROM towary; oraz na zrzucie widoczne są jedynie nazwy wszystkich produktów (10 nazw)

    ok. 1 min
    Polecenie z arkusza

    Zapytanie 3: wybierające jedynie pole nazwa dla wszystkich rekordów w tabeli towary

    SELECT nazwa FROM towary; - bez warunku, więc wszystkie 10 nazw (R.1.5). Zrzut: kw3.jpg. Strona z tego zapytania nie korzysta - arkusz każe tylko je zapisać i wykonać.

    kwerendy.txt Tekst zmienione: 3 linie
    -- Zapytanie 1
    SELECT nazwa, cena FROM towary LIMIT 4;
    
    -- Zapytanie 2
    SELECT cena FROM towary WHERE nazwa = 'Cyrkiel';
    
    -- Zapytanie 3
    SELECT nazwa FROM towary;
    Podgląd strony po tym kroku
    Podgląd strony po kroku 6
  7. Krok 7: Zapytanie 4: liczba towarów w promocji i poza nią

    Kryteria:

    R.1.6 Zapisano zapytanie 4 wybierające jedynie pole promocja z tabeli towary oraz zliczające ilość towarów objętych i towarów nieobjętych promocją. Pole zliczające nazwano ilosc. W pliku z kwerendami lub na zrzucie istnieje zapis np.: SELECT promocja, COUNT(nazwa) AS ilosc FROM towary GROUP BY promocja; oraz Na zrzucie widoczne są jedynie następujące dane: 0 i 6 oraz 1 i 4

    ok. 3 min
    Polecenie z arkusza

    Zapytanie 4: wybierające jedynie pole promocja dla wszystkich rekordów z tabeli towary oraz zliczające ilość towarów objętych i towarów nieobjętych promocją. Pole zliczające należy nazwać ilosc.

    • SELECT promocja, COUNT(nazwa) AS ilosc - wartość pola promocja i liczba towarów; AS ilosc nadaje kolumnie nazwę z arkusza,
    • FROM towary,
    • GROUP BY promocja - towary z tą samą wartością promocja tworzą grupę, a COUNT liczy każdą osobno. Pole przyjmuje tylko 0 i 1, więc grupy są dwie.

    Wynik: 0 - 6 (poza promocją) i 1 - 4 (w promocji) (R.1.6). Zrzut: kw4.jpg.

    Typowe błędy

    Bez GROUP BY zapytanie zwraca jeden wiersz z liczbą 10 - a arkusz chce osobno towary objęte i nieobjęte promocją.

    kwerendy.txt Tekst zmienione: 3 linie
    -- Zapytanie 1
    SELECT nazwa, cena FROM towary LIMIT 4;
    
    -- Zapytanie 2
    SELECT cena FROM towary WHERE nazwa = 'Cyrkiel';
    
    -- Zapytanie 3
    SELECT nazwa FROM towary;
    
    -- Zapytanie 4
    SELECT promocja, COUNT(nazwa) AS ilosc FROM towary GROUP BY promocja;
    Podgląd strony po tym kroku
    Podgląd strony po kroku 7
  8. Etap 2: Grafika

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

    Krok 8: Przeskalowanie zakupy.png do szerokości 150 px

    ok. 2 min
    Polecenie z arkusza

    Plik zakupy.png, wypakowany z archiwum, należy przeskalować z zachowaniem proporcji tak, aby jego szerokość wynosiła dokładnie 150 px

    zakupy.png ma 377 × 340 px. W GIMP-ie Obraz → Skaluj obraz z zamkniętym łańcuchem przy szerokości i wysokości, szerokość 150 px - wysokość przeliczy się sama: 340 · 150 / 377 ≈ 135 px.

    Typowe błędy

    Rozpięty łańcuch i ręcznie wpisana wysokość zniekształcą wózek - kryterium wymaga zachowania proporcji i wysokości 135 px.

    Podgląd strony po tym kroku
    Podgląd strony po kroku 8
  9. Krok 9: Zapis jako zakupy2.png z przezroczystością

    Kryteria:

    R.2.1 Obraz przeskalowano z zachowaniem proporcji tak, aby szerokość wynosiła 150 px, odpowiadająca temu wysokość wynosi 135 px oraz zapisano w pliku z rozszerzeniem png z zachowaniem przezroczystości

    ok. 2 min
    Polecenie z arkusza

    Plik po przeskalowaniu należy zapisać jako zakupy2.png, z zachowaniem pozostałych atrybutów, w tym przezroczystości

    Plik → Eksportuj jako, nazwa zakupy2.png, z zapisywaniem kanału alfa - tło wokół wózka zostaje przezroczyste i prześwituje przez nie szary kolor panelu środkowego. Przeskalowanie do 150 × 135 px i plik PNG z przezroczystością dają razem R.2.1. Plik zakupy.png zostaje w folderze bez zmian - jest na liście plików do oddania.

    Podgląd: zakupy2.png na tle panelu środkowego.

    Typowe błędy

    Eksport do JPEG albo spłaszczenie obrazu usuwa przezroczystość - na szarym panelu pojawia się biały prostokąt.

    Podgląd strony po tym kroku
    Podgląd strony po kroku 9
  10. Etap 3: Strona index.php

    Kroki 10-25 · po tym etapie masz 19 z 39 kryteriów (pkt)

    Krok 10: Plik index.php

    ok. 1 min
    Polecenie z arkusza

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

    Witryna ma jedną stronę - index.php. Rozszerzenie .php, bo na stronie staną dwa skrypty; dopóki nie ma w niej kodu PHP, serwer odda ją przeglądarce jak zwykły HTML. lang="pl" mówi przeglądarce, że treść jest po polsku.

    index.php PHP nowy plik
    <!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

    Kryteria:

    R.2.2 Witrynę internetową zapisano w pliku index.php oraz zastosowano właściwy standard kodowania polskich znaków

    ok. 1 min
    Polecenie z arkusza

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

    <meta charset="UTF-8"> jako pierwsza rzecz w <head>; plik zapisz w edytorze w kodowaniu UTF-8. Strona index.php z właściwym kodowaniem daje R.2.2.

    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: Tytuł strony

    Kryteria:

    R.2.3 Nadano tytuł stronie "Artykuły biurowe”, jest on widoczny na karcie przeglądarki

    ok. 1 min
    Polecenie z arkusza

    Tytuł strony widoczny na karcie przeglądarki: „Artykuły biurowe”

    <title> w <head> - napis na karcie przeglądarki (R.2.3).

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

    Kryteria:

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

    ok. 1 min
    Polecenie z arkusza

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

    <link rel="stylesheet" href="styl.css"> w <head> (R.3.5). Od tej chwili żadnych atrybutów style w HTML-u - klucz wymaga, żeby formatowanie pochodziło wyłącznie z pliku CSS.

    index.php PHP zmienione: 1 linia
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <title>Artykuły biurowe</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
    </body>
    </html>
    Podgląd strony po tym kroku (index.php)
  14. Krok 14: Bloki: baner, trzy panele i stopka

    Kryteria:

    R.2.4 Układ strony zdefiniowano dzieląc ją na baner, panele lewy, środkowy, prawy oraz stopkę. Zastosowano znaczniki sekcji

    ok. 2 min
    Polecenie z arkusza

    Podział strony na bloki: na górze baner, poniżej bloki: lewy, środkowy i prawy oraz na dole blok stopki. Podział zrealizowany za pomocą znaczników sekcji tak, aby po uruchomieniu w przeglądarce wygląd układu bloków był zgodny z obrazem 2

    Baner to <header>, stopka <footer>, a trzy panele - znaczniki <section> z identyfikatorami left, middle i right (R.2.4). Każdy panel ma inne tło, szerokość i wyrównanie, więc w CSS dostanie własną regułę. Ułożenie paneli obok siebie ustawi styl.

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

    ok. 1 min
    Polecenie z arkusza

    Zawartość banera: nagłówek pierwszego stopnia o treści „W naszej hurtowni kupisz najtaniej”

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

    index.php PHP zmienione: 1 linia
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <title>Artykuły biurowe</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <header>
            <h1>W naszej hurtowni kupisz najtaniej</h1>
        </header>
        <section id="left">
        </section>
        <section id="middle">
        </section>
        <section id="right">
        </section>
        <footer>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (index.php)
  16. Krok 16: Panel lewy: nagłówek czwartego stopnia

    ok. 1 min
    Polecenie z arkusza

    Zawartość bloku lewego: Nagłówek czwartego stopnia o treści „Ile będą kosztować Twoje zakupy?”

    <h4> - nagłówek czwartego stopnia. W tym arkuszu panele mają nagłówki h4, a stopka h2 - kolejność stopni jest nietypowa, ale tak wymaga arkusz.

    index.php PHP zmienione: 1 linia
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <title>Artykuły biurowe</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <header>
            <h1>W naszej hurtowni kupisz najtaniej</h1>
        </header>
        <section id="left">
            <h4>Ile będą kosztować Twoje zakupy?</h4>
        </section>
        <section id="middle">
        </section>
        <section id="right">
        </section>
        <footer>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (index.php)
  17. Krok 17: Formularz wysyłany metodą post

    Kryteria:

    R.3.2 Dane z formularza przesyłane są za pomocą metody POST

    ok. 1 min
    Polecenie z arkusza

    Formularz wysyła dane do serwera za pomocą przycisku OBLICZ, metodą post

    method="post" - dane jadą w treści żądania, nie w adresie strony (R.3.2). Bez atrybutu action formularz wysyła dane do tej samej strony, czyli do index.php - tam będzie czekał skrypt 2.

    index.php PHP zmienione: 2 linie
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <title>Artykuły biurowe</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <header>
            <h1>W naszej hurtowni kupisz najtaniej</h1>
        </header>
        <section id="left">
            <h4>Ile będą kosztować Twoje zakupy?</h4>
            <form method="post">
            </form>
        </section>
        <section id="middle">
        </section>
        <section id="right">
        </section>
        <footer>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (index.php)
  18. Krok 18: Napis i lista rozwijana z sześcioma artykułami

    Kryteria:

    R.2.7 Na stronie umieszczono listę rozwijalną, zawierającą nazwy produktów (Zeszyt 60 kartek, Zeszyt 32 kartki, Cyrkiel, Linijka 30 cm., Ekierka, Linijka 50 cm.) użyto znaczników <select>, <option> oraz ich zamknięcia

    ok. 2 min
    Polecenie z arkusza

    Formularz zgodny z obrazem 4, zawierający: Napis „wybierz artykuł”. Listę rozwijalną zgodną z obrazem 5, zawierającą nazwy wszystkich towarów: Zeszyt 60 kartek, Zeszyt 32 kartki, Cyrkiel, Linijka 30 cm, Ekierka, Linijka 50 cm

    Napis to zwykły tekst w formularzu, lista rozwijana - <select> z sześcioma <option> w kolejności z obrazu 5 (R.2.7). name="product" to nazwa, pod którą wybór trafi do skryptu: $_POST['product']. Opcja bez atrybutu value wysyła swój tekst, więc skrypt dostanie nazwę towaru. <br> przenosi pole liczby sztuk do następnego wiersza, jak na obrazie 4.

    Arkusz pisze „wszystkich towarów”, ale wymienia sześć - to towary spoza promocji (pozostałe cztery są w promocji). Lista ma dokładnie te sześć nazw, tak jak obraz 5 i klucz.

    Typowe błędy

    Nazwa opcji musi być identyczna z nazwą w bazie - „Linijka 30cm” bez spacji nie znajdzie ceny w zapytaniu 2.

    index.php PHP zmienione: 9 linii
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <title>Artykuły biurowe</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <header>
            <h1>W naszej hurtowni kupisz najtaniej</h1>
        </header>
        <section id="left">
            <h4>Ile będą kosztować Twoje zakupy?</h4>
            <form method="post">
                wybierz artykuł
                <select name="product">
                    <option>Zeszyt 60 kartek</option>
                    <option>Zeszyt 32 kartki</option>
                    <option>Cyrkiel</option>
                    <option>Linijka 30 cm</option>
                    <option>Ekierka</option>
                    <option>Linijka 50 cm</option>
                </select><br>
            </form>
        </section>
        <section id="middle">
        </section>
        <section id="right">
        </section>
        <footer>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (index.php)
  19. Krok 19: Pole liczby sztuk z wartością 0

    ok. 1 min
    Polecenie z arkusza

    Pole edycyjne typu numerycznego z wartością domyślną 0 poprzedzone napisem „liczba sztuk:”

    type="number" - pole na liczbę ze strzałkami do zmiany wartości, value="0" - wartość domyślna. id="quantity" przyda się w CSS (margines pola), a name="quantity" - w skrypcie 2.

    Typowe błędy

    Obraz 4 pokazuje puste pole, ale arkusz i klucz (R.2.8) wymagają wartości 0 - pole bez value="0" traci punkt.

    index.php PHP zmienione: 1 linia
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <title>Artykuły biurowe</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <header>
            <h1>W naszej hurtowni kupisz najtaniej</h1>
        </header>
        <section id="left">
            <h4>Ile będą kosztować Twoje zakupy?</h4>
            <form method="post">
                wybierz artykuł
                <select name="product">
                    <option>Zeszyt 60 kartek</option>
                    <option>Zeszyt 32 kartki</option>
                    <option>Cyrkiel</option>
                    <option>Linijka 30 cm</option>
                    <option>Ekierka</option>
                    <option>Linijka 50 cm</option>
                </select><br>
                liczba sztuk: <input type="number" name="quantity" value="0" id="quantity"><br>
            </form>
        </section>
        <section id="middle">
        </section>
        <section id="right">
        </section>
        <footer>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (index.php)
  20. Krok 20: Przycisk OBLICZ

    Kryteria: ,

    R.2.8 Na stronie umieszczono pole edycyjne typu numerycznego z wartością początkową ustawioną na 0 oraz przycisk OBLICZ

    R.3.3 Przycisk wysyła dane z formularza (input lub button z typem submit lub button bez typu)

    ok. 1 min
    Polecenie z arkusza

    Przycisk „OBLICZ” - realizujący skrypt 2

    type="submit" wysyła formularz (R.3.3), value to napis na przycisku. Pole liczbowe z zerem i przycisk OBLICZ dają R.2.8.

    index.php PHP zmienione: 1 linia
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <title>Artykuły biurowe</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <header>
            <h1>W naszej hurtowni kupisz najtaniej</h1>
        </header>
        <section id="left">
            <h4>Ile będą kosztować Twoje zakupy?</h4>
            <form method="post">
                wybierz artykuł
                <select name="product">
                    <option>Zeszyt 60 kartek</option>
                    <option>Zeszyt 32 kartki</option>
                    <option>Cyrkiel</option>
                    <option>Linijka 30 cm</option>
                    <option>Ekierka</option>
                    <option>Linijka 50 cm</option>
                </select><br>
                liczba sztuk: <input type="number" name="quantity" value="0" id="quantity"><br>
                <input type="submit" value="OBLICZ">
            </form>
        </section>
        <section id="middle">
        </section>
        <section id="right">
        </section>
        <footer>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (index.php)
  21. Krok 21: Panel środkowy: obraz zakupy2.png

    Kryteria:

    R.2.9 Na stronie umieszczono obraz z rozszerzeniem png z tekstem alternatywnym "hurtownia"

    ok. 1 min
    Polecenie z arkusza

    Zawartość bloku środkowego: Obraz zakupy2.png z tekstem alternatywnym „hurtownia”

    src - przeskalowany plik, alt - tekst, który przeczyta czytnik ekranu albo pokaże przeglądarka, gdy obraz się nie wczyta (R.2.9).

    index.php PHP zmienione: 1 linia
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <title>Artykuły biurowe</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <header>
            <h1>W naszej hurtowni kupisz najtaniej</h1>
        </header>
        <section id="left">
            <h4>Ile będą kosztować Twoje zakupy?</h4>
            <form method="post">
                wybierz artykuł
                <select name="product">
                    <option>Zeszyt 60 kartek</option>
                    <option>Zeszyt 32 kartki</option>
                    <option>Cyrkiel</option>
                    <option>Linijka 30 cm</option>
                    <option>Ekierka</option>
                    <option>Linijka 50 cm</option>
                </select><br>
                liczba sztuk: <input type="number" name="quantity" value="0" id="quantity"><br>
                <input type="submit" value="OBLICZ">
            </form>
        </section>
        <section id="middle">
            <img src="zakupy2.png" alt="hurtownia">
        </section>
        <section id="right">
        </section>
        <footer>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (index.php)
  22. Krok 22: Panel środkowy: Kontakt i akapit w dwóch wierszach

    Kryteria:

    R.2.10 Na stronie umieszczono akapit lub 2 akapity z tekstem „telefon: 888999777 e-mail: [email protected]” oraz tekst jest podzielony wyłącznie na dwa wiersze (zgodnie z obrazem 2 w arkuszu

    ok. 1 min
    Polecenie z arkusza

    Nagłówek czwartego stopnia o treści „Kontakt”. Umieszczony w akapicie (paragrafie) tekst „telefon: 888999777 e-mail: [email protected]” podzielony na dwa wiersze (zgodnie z obrazem 2)

    <h4> pod obrazem, a pod nim jeden akapit <p> z <br> - telefon i e-mail w dwóch wierszach bez odstępu między nimi, jak na obrazie 2 (R.2.10).

    index.php PHP zmienione: 2 linie
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <title>Artykuły biurowe</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <header>
            <h1>W naszej hurtowni kupisz najtaniej</h1>
        </header>
        <section id="left">
            <h4>Ile będą kosztować Twoje zakupy?</h4>
            <form method="post">
                wybierz artykuł
                <select name="product">
                    <option>Zeszyt 60 kartek</option>
                    <option>Zeszyt 32 kartki</option>
                    <option>Cyrkiel</option>
                    <option>Linijka 30 cm</option>
                    <option>Ekierka</option>
                    <option>Linijka 50 cm</option>
                </select><br>
                liczba sztuk: <input type="number" name="quantity" value="0" id="quantity"><br>
                <input type="submit" value="OBLICZ">
            </form>
        </section>
        <section id="middle">
            <img src="zakupy2.png" alt="hurtownia">
            <h4>Kontakt</h4>
            <p>telefon: 888999777<br>e-mail: [email protected]</p>
        </section>
        <section id="right">
        </section>
        <footer>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (index.php)
  23. Krok 23: Odsyłacz pocztowy [email protected]

    Kryteria:

    R.3.4 Napis [email protected] jest odsyłaczem pocztowym mającym postać np.: <a href= "mailto:[email protected]" >…

    ok. 1 min
    Polecenie z arkusza

    Napis [email protected] jest odsyłaczem pocztowym łączącym z tym samym adresem

    Odsyłacz pocztowy to <a> z adresem mailto: przed adresem e-mail (R.3.4). Kliknięcie otwiera program pocztowy z nową wiadomością.

    Typowe błędy

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

    index.php PHP zmienione: 1 linia
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <title>Artykuły biurowe</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <header>
            <h1>W naszej hurtowni kupisz najtaniej</h1>
        </header>
        <section id="left">
            <h4>Ile będą kosztować Twoje zakupy?</h4>
            <form method="post">
                wybierz artykuł
                <select name="product">
                    <option>Zeszyt 60 kartek</option>
                    <option>Zeszyt 32 kartki</option>
                    <option>Cyrkiel</option>
                    <option>Linijka 30 cm</option>
                    <option>Ekierka</option>
                    <option>Linijka 50 cm</option>
                </select><br>
                liczba sztuk: <input type="number" name="quantity" value="0" id="quantity"><br>
                <input type="submit" value="OBLICZ">
            </form>
        </section>
        <section id="middle">
            <img src="zakupy2.png" alt="hurtownia">
            <h4>Kontakt</h4>
            <p>telefon: 888999777<br>e-mail: <a href="mailto:[email protected]">[email protected]</a></p>
        </section>
        <section id="right">
        </section>
        <footer>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (index.php)
  24. Krok 24: Panel prawy: nagłówek i tabela

    ok. 1 min
    Polecenie z arkusza

    Zawartość bloku prawego: Nagłówek czwartego stopnia o treści „Ceny wybranych artykułów w hurtowni:”. Tabela zgodna z obrazem 3, składająca się z czterech wierszy i dwóch kolumn. Zawartość tabeli generowana jest skryptem 1

    <h4> i pusta tabela <table> - wiersze <tr> z komórkami <td> wypisze skrypt 1 z wyniku zapytania 1: cztery wiersze, w każdym nazwa i cena.

    index.php PHP zmienione: 3 linie
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <title>Artykuły biurowe</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <header>
            <h1>W naszej hurtowni kupisz najtaniej</h1>
        </header>
        <section id="left">
            <h4>Ile będą kosztować Twoje zakupy?</h4>
            <form method="post">
                wybierz artykuł
                <select name="product">
                    <option>Zeszyt 60 kartek</option>
                    <option>Zeszyt 32 kartki</option>
                    <option>Cyrkiel</option>
                    <option>Linijka 30 cm</option>
                    <option>Ekierka</option>
                    <option>Linijka 50 cm</option>
                </select><br>
                liczba sztuk: <input type="number" name="quantity" value="0" id="quantity"><br>
                <input type="submit" value="OBLICZ">
            </form>
        </section>
        <section id="middle">
            <img src="zakupy2.png" alt="hurtownia">
            <h4>Kontakt</h4>
            <p>telefon: 888999777<br>e-mail: <a href="mailto:[email protected]">[email protected]</a></p>
        </section>
        <section id="right">
            <h4>Ceny wybranych artykułów w hurtowni:</h4>
            <table>
            </table>
        </section>
        <footer>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (index.php)
  25. Krok 25: Stopka: autor witryny

    Kryteria:

    R.2.5 Zapisano wszystkie nagłówki: w banerze - h1 "W naszej hurtowni kupisz najtaniej”, w bloku lewym - h4 "Ile będą kosztować Twoje zakupy?”, w bloku środkowym - h4 "Kontakt", w bloku prawym - h4 "Ceny wybranych artykułów w hurtowni:”,, w stopce - h2 "Witrynę wykonał" i dalej wstawiony numer PESEL zdającego

    ok. 1 min
    Polecenie z arkusza

    Zawartość stopki: nagłówek drugiego stopnia o treści „Witrynę wykonał”, dalej wstawiony Twój numer PESEL

    <h2> w stopce. Na egzaminie po napisie wpisujesz swój numer PESEL; w tym rozwiązaniu w jego miejscu stoi imię i nazwisko autora: Bartosz Bryniarski. Komplet nagłówków: h1 w banerze, trzy h4 w panelach i h2 w stopce (R.2.5).

    index.php PHP zmienione: 1 linia
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <title>Artykuły biurowe</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <header>
            <h1>W naszej hurtowni kupisz najtaniej</h1>
        </header>
        <section id="left">
            <h4>Ile będą kosztować Twoje zakupy?</h4>
            <form method="post">
                wybierz artykuł
                <select name="product">
                    <option>Zeszyt 60 kartek</option>
                    <option>Zeszyt 32 kartki</option>
                    <option>Cyrkiel</option>
                    <option>Linijka 30 cm</option>
                    <option>Ekierka</option>
                    <option>Linijka 50 cm</option>
                </select><br>
                liczba sztuk: <input type="number" name="quantity" value="0" id="quantity"><br>
                <input type="submit" value="OBLICZ">
            </form>
        </section>
        <section id="middle">
            <img src="zakupy2.png" alt="hurtownia">
            <h4>Kontakt</h4>
            <p>telefon: 888999777<br>e-mail: <a href="mailto:[email protected]">[email protected]</a></p>
        </section>
        <section id="right">
            <h4>Ceny wybranych artykułów w hurtowni:</h4>
            <table>
            </table>
        </section>
        <footer>
            <h2>Witrynę wykonał Bartosz Bryniarski</h2>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (index.php)
  26. Etap 4: Styl CSS

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

    Krok 26: Plik styl.css: baner

    ok. 2 min
    Polecenie z arkusza

    Format banera: kolor tła #A61C2E, wysokość 70 px, wielkość czcionki 110%, wyrównanie tekstu do środka

    Nowy plik styl.css w folderze zdającego. Selektor znacznika header: kolor tła zapisany szesnastkowo, wysokość, czcionka 110% rozmiaru dziedziczonego i wyśrodkowanie.

    styl.css CSS nowy plik
    header {
        background-color: #A61C2E;
        height: 70px;
        font-size: 110%;
        text-align: center;
    }
    Podgląd strony po tym kroku (index.php)
  27. Krok 27: Panel lewy

    ok. 1 min
    Polecenie z arkusza

    Format panelu lewego: kolor tła #A61C2E, wysokość 550 px, szerokość 35%, wielkość czcionki 110%, wyrównanie tekstu do środka

    Selektor identyfikatora #left - z krzyżykiem, bo w HTML-u jest id="left". Panel lewy ma ten sam kolor co baner.

    Typowe błędy

    Kropka zamiast krzyżyka (.left) to selektor klasy - reguła nie trafi w panel, a klucz przy R.3.5 uznaje wtedy połączenie ze stylem za niespełnione.

    styl.css CSS zmienione: 7 linii
    header {
        background-color: #A61C2E;
        height: 70px;
        font-size: 110%;
        text-align: center;
    }
    #left {
        background-color: #A61C2E;
        height: 550px;
        width: 35%;
        font-size: 110%;
        text-align: center;
    }
    Podgląd strony po tym kroku (index.php)
  28. Krok 28: Panel środkowy

    ok. 1 min
    Polecenie z arkusza

    Format panelu środkowego: kolor tła #4D524A, wysokość 550 px, szerokość 30%, wyrównanie tekstu do środka

    Jedyny szary blok na stronie i jedyny bez powiększonej czcionki.

    styl.css CSS zmienione: 6 linii
    header {
        background-color: #A61C2E;
        height: 70px;
        font-size: 110%;
        text-align: center;
    }
    #left {
        background-color: #A61C2E;
        height: 550px;
        width: 35%;
        font-size: 110%;
        text-align: center;
    }
    #middle {
        background-color: #4D524A;
        height: 550px;
        width: 30%;
        text-align: center;
    }
    Podgląd strony po tym kroku (index.php)
  29. Krok 29: Panel prawy

    Kryteria:

    R.4.4 Ustawiono szerokość panelu lewego i prawego na 35% oraz panelu środkowego na 30%

    ok. 1 min
    Polecenie z arkusza

    Format panelu prawego: kolor tła #A61C2E, wysokość 550 px, szerokość 35%, wielkość czcionki 110%, wyrównanie tekstu do prawej

    Szerokości 35% + 30% + 35% = 100% (R.4.4). Panel prawy wyrównuje tekst do prawej - nagłówek stoi przy prawej krawędzi, jak na obrazie 2.

    styl.css CSS zmienione: 7 linii
    header {
        background-color: #A61C2E;
        height: 70px;
        font-size: 110%;
        text-align: center;
    }
    #left {
        background-color: #A61C2E;
        height: 550px;
        width: 35%;
        font-size: 110%;
        text-align: center;
    }
    #middle {
        background-color: #4D524A;
        height: 550px;
        width: 30%;
        text-align: center;
    }
    #right {
        background-color: #A61C2E;
        height: 550px;
        width: 35%;
        font-size: 110%;
        text-align: right;
    }
    Podgląd strony po tym kroku (index.php)
  30. Krok 30: Stopka

    Kryteria: ,

    R.4.1 Ustawiono kolor tła dla banera, stopki, panelu lewego i prawego na #A61C2E oraz panelu środkowego na #4D524A

    R.4.2 Ustawiono wysokość banera i stopki na 70px oraz paneli: lewego, prawego i środkowego na 550px

    ok. 1 min
    Polecenie z arkusza

    Format stopki: kolor tła #A61C2E, wysokość 70 px, wyrównanie tekstu do prawej

    Kolory tła wszystkich bloków (R.4.1) i wysokości 70/550/70 px (R.4.2) są ustawione.

    styl.css CSS zmienione: 5 linii
    header {
        background-color: #A61C2E;
        height: 70px;
        font-size: 110%;
        text-align: center;
    }
    #left {
        background-color: #A61C2E;
        height: 550px;
        width: 35%;
        font-size: 110%;
        text-align: center;
    }
    #middle {
        background-color: #4D524A;
        height: 550px;
        width: 30%;
        text-align: center;
    }
    #right {
        background-color: #A61C2E;
        height: 550px;
        width: 35%;
        font-size: 110%;
        text-align: right;
    }
    footer {
        background-color: #A61C2E;
        height: 70px;
        text-align: right;
    }
    Podgląd strony po tym kroku (index.php)
  31. Krok 31: Tabela: margines lewy i brak odstępów

    ok. 1 min
    Polecenie z arkusza

    Format tabeli: margines zewnętrzny lewy 150 px, obramowanie komórek tabeli linią kropkowaną (brak odstępów pomiędzy komórkami)

    • margin-left: 150px - tabela odsunięta od lewej krawędzi panelu (wyrównanie do prawej dotyczy tekstu, nie tabeli),
    • border-collapse: collapse - sąsiednie komórki mają wspólną krawędź zamiast dwóch osobnych ramek z odstępem; to jest „brak odstępów pomiędzy komórkami”.

    Samą linię kropkowaną dostaną komórki w następnym kroku.

    styl.css CSS zmienione: 4 linie
    header {
        background-color: #A61C2E;
        height: 70px;
        font-size: 110%;
        text-align: center;
    }
    #left {
        background-color: #A61C2E;
        height: 550px;
        width: 35%;
        font-size: 110%;
        text-align: center;
    }
    #middle {
        background-color: #4D524A;
        height: 550px;
        width: 30%;
        text-align: center;
    }
    #right {
        background-color: #A61C2E;
        height: 550px;
        width: 35%;
        font-size: 110%;
        text-align: right;
    }
    footer {
        background-color: #A61C2E;
        height: 70px;
        text-align: right;
    }
    table {
        margin-left: 150px;
        border-collapse: collapse;
    }
    Podgląd strony po tym kroku (index.php)
  32. Krok 32: Komórki tabeli

    Kryteria: , , ,

    R.4.3 Ustawiono wyrównanie tekstu do środka dla: banera, panelu lewego i środkowego, komórek tabeli oraz wyrównanie tekstu do prawej dla panelu prawego i stopki

    R.4.5 Ustawiono wielkość czcionki dla banera, paneli lewego i prawego oraz komórek tabeli na 110%

    R.4.6 Ustawiono marginesy wewnętrzne (padding) dla komórek tabeli na 10px

    R.4.8 Ustawiono obramowanie komórek tabeli linią pojedynczą kropkowaną niebieską (dowolny odcień) o grubości 2px (właściwość border)

    ok. 2 min
    Polecenie z arkusza

    Format komórek tabeli: obramowanie linią kropkowaną niebieską o szerokości 2 px, marginesy wewnętrzne 10 px, wyrównanie tekstu do środka, wielkość czcionki 110%

    • border: 2px dotted blue - grubość, styl (dotted - kropkowana) i kolor w jednej właściwości (R.4.8),
    • padding: 10px - margines wewnętrzny komórki (R.4.6),
    • text-align: center i font-size: 110%.

    Wyśrodkowanie banera, panelu lewego, środkowego i komórek oraz wyrównanie do prawej panelu prawego i stopki daje R.4.3, czcionka 110% w banerze, panelach bocznych i komórkach - R.4.5.

    styl.css CSS zmienione: 6 linii
    header {
        background-color: #A61C2E;
        height: 70px;
        font-size: 110%;
        text-align: center;
    }
    #left {
        background-color: #A61C2E;
        height: 550px;
        width: 35%;
        font-size: 110%;
        text-align: center;
    }
    #middle {
        background-color: #4D524A;
        height: 550px;
        width: 30%;
        text-align: center;
    }
    #right {
        background-color: #A61C2E;
        height: 550px;
        width: 35%;
        font-size: 110%;
        text-align: right;
    }
    footer {
        background-color: #A61C2E;
        height: 70px;
        text-align: right;
    }
    table {
        margin-left: 150px;
        border-collapse: collapse;
    }
    td {
        border: 2px dotted blue;
        padding: 10px;
        text-align: center;
        font-size: 110%;
    }
    Podgląd strony po tym kroku (index.php)
  33. Krok 33: Wiersz pod kursorem na niebiesko

    Kryteria:

    R.4.9 Ustawiono styl dla wierszy tabeli z pseudoklasą hover: po najechaniu kursorem na wybrany wiersz tekst zmienia kolor na niebieski (dowolny odcień)

    ok. 1 min
    Polecenie z arkusza

    Po wskazaniu kursorem myszki wybranego wiersza tabeli zmienia się kolor tekstu w tym wierszu na niebieski

    Pseudoklasa :hover działa, gdy kursor jest nad elementem. tr:hover dotyczy całego wiersza - obie komórki zmieniają kolor naraz, bo dziedziczą kolor tekstu po wierszu (R.4.9).

    Typowe błędy

    td:hover zmieni kolor tylko jednej komórki, a arkusz mówi o wierszu.

    styl.css CSS zmienione: 3 linie
    header {
        background-color: #A61C2E;
        height: 70px;
        font-size: 110%;
        text-align: center;
    }
    #left {
        background-color: #A61C2E;
        height: 550px;
        width: 35%;
        font-size: 110%;
        text-align: center;
    }
    #middle {
        background-color: #4D524A;
        height: 550px;
        width: 30%;
        text-align: center;
    }
    #right {
        background-color: #A61C2E;
        height: 550px;
        width: 35%;
        font-size: 110%;
        text-align: right;
    }
    footer {
        background-color: #A61C2E;
        height: 70px;
        text-align: right;
    }
    table {
        margin-left: 150px;
        border-collapse: collapse;
    }
    td {
        border: 2px dotted blue;
        padding: 10px;
        text-align: center;
        font-size: 110%;
    }
    tr:hover {
        color: blue;
    }
    Podgląd strony po tym kroku (index.php)
  34. Krok 34: Obraz, nagłówki h4 i pole liczby sztuk

    Kryteria: ,

    R.4.7 Ustawiono wyłącznie margines zewnętrzny górny (margin-top) dla pola edycyjnego na 5px oraz wyłącznie margines zewnętrzny górny (margin-top) dla obrazu i nagłówka h4 na 80px oraz wyłącznie margines zewnętrzny lewy (margin-left) dla tabeli na 150px

    R.4.10 Ustawiono biały kolor tekstu dla nagłówka h4

    ok. 2 min
    Polecenie z arkusza

    Formatowanie obrazu: margines zewnętrzny górny 80 px. Formatowanie nagłówka czwartego stopnia: kolor tekstu biały, margines zewnętrzny górny 80 px. Formatowanie pola edycyjnego: margines zewnętrzny górny 5 px

    Same marginesy górne (margin-top) - klucz pisze „wyłącznie margines zewnętrzny górny”, więc bez margin z czterema wartościami (R.4.7). Nagłówki h4 są białe (R.4.10). Pole liczby sztuk wybiera selektor #quantity.

    styl.css CSS zmienione: 10 linii
    header {
        background-color: #A61C2E;
        height: 70px;
        font-size: 110%;
        text-align: center;
    }
    #left {
        background-color: #A61C2E;
        height: 550px;
        width: 35%;
        font-size: 110%;
        text-align: center;
    }
    #middle {
        background-color: #4D524A;
        height: 550px;
        width: 30%;
        text-align: center;
    }
    #right {
        background-color: #A61C2E;
        height: 550px;
        width: 35%;
        font-size: 110%;
        text-align: right;
    }
    footer {
        background-color: #A61C2E;
        height: 70px;
        text-align: right;
    }
    table {
        margin-left: 150px;
        border-collapse: collapse;
    }
    td {
        border: 2px dotted blue;
        padding: 10px;
        text-align: center;
        font-size: 110%;
    }
    tr:hover {
        color: blue;
    }
    img {
        margin-top: 80px;
    }
    h4 {
        color: white;
        margin-top: 80px;
    }
    #quantity {
        margin-top: 5px;
    }
    Podgląd strony po tym kroku (index.php)
  35. Krok 35: Układ bloków zgodny z obrazem 2

    Kryteria:

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

    ok. 2 min
    Polecenie z arkusza

    Podział strony na bloki: na górze baner, poniżej bloki: lewy, środkowy i prawy oraz na dole blok stopki. Podział zrealizowany za pomocą znaczników sekcji tak, aby po uruchomieniu w przeglądarce wygląd układu bloków był zgodny z obrazem 2

    Sekcje z float: left stają kolejno od lewej krawędzi, a że mają razem dokładnie 100% szerokości, mieszczą się w jednym rzędzie. Stopka z clear: both zaczyna się pod panelami. Układ odpowiada obrazowi 2 (R.3.1).

    Typowe błędy

    Panele o sumie szerokości 100% nie mogą mieć obramowań ani padding po bokach - każdy piksel więcej spycha panel prawy pod środkowy.

    styl.css CSS zmienione: 6 linii
    header {
        background-color: #A61C2E;
        height: 70px;
        font-size: 110%;
        text-align: center;
    }
    #left {
        background-color: #A61C2E;
        height: 550px;
        width: 35%;
        font-size: 110%;
        text-align: center;
    }
    #middle {
        background-color: #4D524A;
        height: 550px;
        width: 30%;
        text-align: center;
    }
    #right {
        background-color: #A61C2E;
        height: 550px;
        width: 35%;
        font-size: 110%;
        text-align: right;
    }
    footer {
        background-color: #A61C2E;
        height: 70px;
        text-align: right;
    }
    table {
        margin-left: 150px;
        border-collapse: collapse;
    }
    td {
        border: 2px dotted blue;
        padding: 10px;
        text-align: center;
        font-size: 110%;
    }
    tr:hover {
        color: blue;
    }
    img {
        margin-top: 80px;
    }
    h4 {
        color: white;
        margin-top: 80px;
    }
    #quantity {
        margin-top: 5px;
    }
    section {
        float: left;
    }
    footer {
        clear: both;
    }
    Podgląd strony po tym kroku (index.php)
  36. Etap 5: Skrypty PHP

    Kroki 36-42 · po tym etapie masz 39 z 39 kryteriów (pkt)

    Krok 36: Połączenie z bazą sklep na początku pliku

    Kryteria: ,

    R.5.1 Skrypt napisano w języku PHP i umieszczono w pliku index.php

    R.5.2 Zastosowano funkcję realizującą połączenie z serwerem bazy danych na localhost, użytkownik root, bez hasła, baza danych sklep

    ok. 3 min
    Polecenie z arkusza

    Skrypt połączenia z bazą. Napisany w języku PHP, umieszczony w pliku index.php. Skrypt łączy się z serwerem bazodanowym na localhost, użytkownik root bez hasła, baza danych o nazwie sklep

    Z bazy korzystają dwa skrypty w dwóch panelach, a połączenie wystarczy jedno - dlatego blok PHP z połączeniem stoi na samym początku pliku, przed <!DOCTYPE html> (R.5.1). Kod między <?php a ?> wykona serwer, zanim strona trafi do przeglądarki.

    mysqli_connect z tabeli 1 arkusza - serwer localhost, użytkownik root, puste hasło '' i baza sklep. Połączenie trafia do zmiennej $connection (R.5.2). Arkusz nie wymaga sprawdzania, czy operacje się powiodły.

    Od tego kroku podgląd to wynik działania strony po stronie serwera (prawdziwe uruchomienie w PHP 8.2). Stronę sprawdzasz przez http://localhost/…/index.php.

    index.php PHP zmienione: 3 linie
    <?php
    $connection = mysqli_connect('localhost', 'root', '', 'sklep');
    ?>
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <title>Artykuły biurowe</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <header>
            <h1>W naszej hurtowni kupisz najtaniej</h1>
        </header>
        <section id="left">
            <h4>Ile będą kosztować Twoje zakupy?</h4>
            <form method="post">
                wybierz artykuł
                <select name="product">
                    <option>Zeszyt 60 kartek</option>
                    <option>Zeszyt 32 kartki</option>
                    <option>Cyrkiel</option>
                    <option>Linijka 30 cm</option>
                    <option>Ekierka</option>
                    <option>Linijka 50 cm</option>
                </select><br>
                liczba sztuk: <input type="number" name="quantity" value="0" id="quantity"><br>
                <input type="submit" value="OBLICZ">
            </form>
        </section>
        <section id="middle">
            <img src="zakupy2.png" alt="hurtownia">
            <h4>Kontakt</h4>
            <p>telefon: 888999777<br>e-mail: <a href="mailto:[email protected]">[email protected]</a></p>
        </section>
        <section id="right">
            <h4>Ceny wybranych artykułów w hurtowni:</h4>
            <table>
            </table>
        </section>
        <footer>
            <h2>Witrynę wykonał Bartosz Bryniarski</h2>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (index.php)
  37. Krok 37: Skrypt 1: zapytanie 1

    Kryteria:

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

    ok. 2 min
    Polecenie z arkusza

    Skrypt 1: Wysyła do bazy danych zapytanie 1 (z pliku kwerendy.txt)

    Skrypt 1 stoi wewnątrz <table>, bo to, co wypisze, ma się znaleźć w tabeli. mysqli_query wysyła zapytanie 1 z kwerendy.txt i zwraca wynik do $result (R.5.4). Podgląd: tabela jeszcze pusta.

    index.php PHP zmienione: 3 linie
    <?php
    $connection = mysqli_connect('localhost', 'root', '', 'sklep');
    ?>
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <title>Artykuły biurowe</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <header>
            <h1>W naszej hurtowni kupisz najtaniej</h1>
        </header>
        <section id="left">
            <h4>Ile będą kosztować Twoje zakupy?</h4>
            <form method="post">
                wybierz artykuł
                <select name="product">
                    <option>Zeszyt 60 kartek</option>
                    <option>Zeszyt 32 kartki</option>
                    <option>Cyrkiel</option>
                    <option>Linijka 30 cm</option>
                    <option>Ekierka</option>
                    <option>Linijka 50 cm</option>
                </select><br>
                liczba sztuk: <input type="number" name="quantity" value="0" id="quantity"><br>
                <input type="submit" value="OBLICZ">
            </form>
        </section>
        <section id="middle">
            <img src="zakupy2.png" alt="hurtownia">
            <h4>Kontakt</h4>
            <p>telefon: 888999777<br>e-mail: <a href="mailto:[email protected]">[email protected]</a></p>
        </section>
        <section id="right">
            <h4>Ceny wybranych artykułów w hurtowni:</h4>
            <table>
    <?php
    $result = mysqli_query($connection, 'SELECT nazwa, cena FROM towary LIMIT 4;');
    ?>
            </table>
        </section>
        <footer>
            <h2>Witrynę wykonał Bartosz Bryniarski</h2>
        </footer>
    </body>
    </html>

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

  38. Krok 38: Skrypt 1: nazwy i ceny w komórkach tabeli

    Kryteria: , ,

    R.2.6 W bloku prawym umieszczono tabelę z 4 wierszami i 2 kolumnami. W kodzie HTML lub PHP użyto znaczników <table>, <tr>, <td> oraz ich zamknięcia

    R.5.5 Skrypt 1 wyświetla dane zwrócone zapytaniem (Zeszyt 60 kartek - 4.5, Zeszyt 32 kartki - 1.2, Cyrkiel - 12.4, Linijka 30 cm - 7.2)

    R.5.6 Dane wyświetlane przez skrypt 1 umieszczone są wewnątrz komórek tabeli (zawartość tabeli jest zgodna z obrazem 3, symbol waluty nie jest wymagany)

    ok. 3 min
    Polecenie z arkusza

    Wyświetla dane pobrane zapytaniem wewnątrz komórek tabeli. W lewej kolumnie tabeli wypisywane są nazwy czterech towarów, w prawej kolumnie tabeli – odpowiadające im ceny (zgodnie z obrazem 3)

    • mysqli_fetch_row($result) zwraca kolejny wiersz jako tablicę numerowaną: $row[0] to nazwa, $row[1] to cena - w kolejności pól z SELECT. Gdy wierszy zabraknie, zwraca null i pętla while się kończy,
    • echo składa wiersz tabeli: <tr> i dwie komórki <td> - nazwa w lewej, cena w prawej.

    Podgląd: cztery wiersze w kropkowanych ramkach - Zeszyt 60 kartek 4.5, Zeszyt 32 kartki 1.2, Cyrkiel 12.4, Linijka 30 cm 7.2 (R.5.5), jak na obrazie 3 (R.5.6). Tabela z czterema wierszami i dwiema kolumnami daje R.2.6.

    index.php PHP zmienione: 3 linie
    <?php
    $connection = mysqli_connect('localhost', 'root', '', 'sklep');
    ?>
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <title>Artykuły biurowe</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <header>
            <h1>W naszej hurtowni kupisz najtaniej</h1>
        </header>
        <section id="left">
            <h4>Ile będą kosztować Twoje zakupy?</h4>
            <form method="post">
                wybierz artykuł
                <select name="product">
                    <option>Zeszyt 60 kartek</option>
                    <option>Zeszyt 32 kartki</option>
                    <option>Cyrkiel</option>
                    <option>Linijka 30 cm</option>
                    <option>Ekierka</option>
                    <option>Linijka 50 cm</option>
                </select><br>
                liczba sztuk: <input type="number" name="quantity" value="0" id="quantity"><br>
                <input type="submit" value="OBLICZ">
            </form>
        </section>
        <section id="middle">
            <img src="zakupy2.png" alt="hurtownia">
            <h4>Kontakt</h4>
            <p>telefon: 888999777<br>e-mail: <a href="mailto:[email protected]">[email protected]</a></p>
        </section>
        <section id="right">
            <h4>Ceny wybranych artykułów w hurtowni:</h4>
            <table>
    <?php
    $result = mysqli_query($connection, 'SELECT nazwa, cena FROM towary LIMIT 4;');
    while ($row = mysqli_fetch_row($result)) {
        echo '<tr><td>' . $row[0] . '</td><td>' . $row[1] . '</td></tr>';
    }
    ?>
            </table>
        </section>
        <footer>
            <h2>Witrynę wykonał Bartosz Bryniarski</h2>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (index.php)
  39. Krok 39: Skrypt 2: artykuł i liczba sztuk z formularza

    ok. 2 min
    Polecenie z arkusza

    Skrypt 2: Pobiera z formularza nazwę produktu wybraną w liście rozwijalnej. Pobiera z formularza ilość wpisaną w polu edycyjnym

    Skrypt 2 stoi pod formularzem, bo jego wynik ma się pokazać poniżej formularza.

    • isset($_POST['product']) jest prawdziwe dopiero po kliknięciu OBLICZ - przy pierwszym wejściu na stronę skrypt niczego nie liczy,
    • $product - nazwa wybrana z listy, $quantity - liczba z pola quantity.

    Podgląd: wysłany formularz - cyrkiel, 3 sztuki. Wartości są w zmiennych, skrypt jeszcze nic nie wypisuje.

    Typowe błędy

    Odczyt $_POST['product'] bez isset przy pierwszym wejściu na stronę daje ostrzeżenie „Undefined array key” wypisane na stronie.

    index.php PHP zmienione: 6 linii
    <?php
    $connection = mysqli_connect('localhost', 'root', '', 'sklep');
    ?>
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <title>Artykuły biurowe</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <header>
            <h1>W naszej hurtowni kupisz najtaniej</h1>
        </header>
        <section id="left">
            <h4>Ile będą kosztować Twoje zakupy?</h4>
            <form method="post">
                wybierz artykuł
                <select name="product">
                    <option>Zeszyt 60 kartek</option>
                    <option>Zeszyt 32 kartki</option>
                    <option>Cyrkiel</option>
                    <option>Linijka 30 cm</option>
                    <option>Ekierka</option>
                    <option>Linijka 50 cm</option>
                </select><br>
                liczba sztuk: <input type="number" name="quantity" value="0" id="quantity"><br>
                <input type="submit" value="OBLICZ">
            </form>
    <?php
    if (isset($_POST['product'])) {
        $product = $_POST['product'];
        $quantity = $_POST['quantity'];
    }
    ?>
        </section>
        <section id="middle">
            <img src="zakupy2.png" alt="hurtownia">
            <h4>Kontakt</h4>
            <p>telefon: 888999777<br>e-mail: <a href="mailto:[email protected]">[email protected]</a></p>
        </section>
        <section id="right">
            <h4>Ceny wybranych artykułów w hurtowni:</h4>
            <table>
    <?php
    $result = mysqli_query($connection, 'SELECT nazwa, cena FROM towary LIMIT 4;');
    while ($row = mysqli_fetch_row($result)) {
        echo '<tr><td>' . $row[0] . '</td><td>' . $row[1] . '</td></tr>';
    }
    ?>
            </table>
        </section>
        <footer>
            <h2>Witrynę wykonał Bartosz Bryniarski</h2>
        </footer>
    </body>
    </html>

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

  40. Krok 40: Skrypt 2: zapytanie 2 z artykułem z formularza

    Kryteria:

    R.5.7 Skrypt 2 wysyła do bazy danych zapytanie 2 zmodyfikowane tak, że w sekcji warunku sprawdzana nazwa produktu jest zgodna z wyborem

    ok. 2 min
    Polecenie z arkusza

    Wysyła do bazy danych zapytanie 2 (z pliku kwerendy.txt), zmodyfikowane w ten sposób, że w sekcji warunku nazwa produktu jest zgodna z wyborem w liście rozwijalnej

    Zapytanie 2, w którym w miejscu 'Cyrkiel' stoi '$product'. Całe zapytanie jest w cudzysłowie "…", więc PHP podstawia wartość zmiennej; apostrofy wewnątrz są ogranicznikami napisu w SQL (R.5.7).

    Typowe błędy

    Zapytanie w apostrofach ('SELECT ... '$product'') - PHP nie podstawi zmiennej, a apostrofy w środku zakończą napis i powstanie błąd składni.

    index.php PHP zmienione: 1 linia
    <?php
    $connection = mysqli_connect('localhost', 'root', '', 'sklep');
    ?>
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <title>Artykuły biurowe</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <header>
            <h1>W naszej hurtowni kupisz najtaniej</h1>
        </header>
        <section id="left">
            <h4>Ile będą kosztować Twoje zakupy?</h4>
            <form method="post">
                wybierz artykuł
                <select name="product">
                    <option>Zeszyt 60 kartek</option>
                    <option>Zeszyt 32 kartki</option>
                    <option>Cyrkiel</option>
                    <option>Linijka 30 cm</option>
                    <option>Ekierka</option>
                    <option>Linijka 50 cm</option>
                </select><br>
                liczba sztuk: <input type="number" name="quantity" value="0" id="quantity"><br>
                <input type="submit" value="OBLICZ">
            </form>
    <?php
    if (isset($_POST['product'])) {
        $product = $_POST['product'];
        $quantity = $_POST['quantity'];
        $result = mysqli_query($connection, "SELECT cena FROM towary WHERE nazwa = '$product';");
    }
    ?>
        </section>
        <section id="middle">
            <img src="zakupy2.png" alt="hurtownia">
            <h4>Kontakt</h4>
            <p>telefon: 888999777<br>e-mail: <a href="mailto:[email protected]">[email protected]</a></p>
        </section>
        <section id="right">
            <h4>Ceny wybranych artykułów w hurtowni:</h4>
            <table>
    <?php
    $result = mysqli_query($connection, 'SELECT nazwa, cena FROM towary LIMIT 4;');
    while ($row = mysqli_fetch_row($result)) {
        echo '<tr><td>' . $row[0] . '</td><td>' . $row[1] . '</td></tr>';
    }
    ?>
            </table>
        </section>
        <footer>
            <h2>Witrynę wykonał Bartosz Bryniarski</h2>
        </footer>
    </body>
    </html>

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

  41. Krok 41: Skrypt 2: wartość zakupów zaokrąglona do 0,1

    Kryteria:

    R.5.8 Skrypt 2 oblicza oraz wyświetla poniżej formularza kwotę powstałą po pomnożeniu ceny pobranej zapytaniem przez ilość pobraną z pola edycyjnego

    ok. 3 min
    Polecenie z arkusza

    Oblicza kwotę zakupów mnożąc cenę pobraną zapytaniem 2 przez ilość pobraną z pola edycyjnego. Obliczona kwota, zaokrąglona do jednego miejsca po przecinku, wyświetlana jest poniżej formularza

    • mysqli_fetch_row($result) - jedyny wiersz wyniku, $row[0] to cena,
    • $row[0] * $quantity - cena razy liczba sztuk,
    • round(…, 1) - jedno miejsce po przecinku. Bez zaokrąglenia 3 zeszyty po 1.2 zł dałyby 3.5999999999999996 - liczby zmiennoprzecinkowe nie zapisują dokładnie ułamków dziesiętnych,
    • echo wypisuje kwotę pod formularzem.

    Podgląd: 3 cyrkle po 12.4 zł - Wartość zakupów: 37.2 zł (R.5.8). Arkusz nie podaje treści napisu - wystarczy sama kwota pod formularzem.

    index.php PHP zmienione: 3 linie
    <?php
    $connection = mysqli_connect('localhost', 'root', '', 'sklep');
    ?>
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <title>Artykuły biurowe</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <header>
            <h1>W naszej hurtowni kupisz najtaniej</h1>
        </header>
        <section id="left">
            <h4>Ile będą kosztować Twoje zakupy?</h4>
            <form method="post">
                wybierz artykuł
                <select name="product">
                    <option>Zeszyt 60 kartek</option>
                    <option>Zeszyt 32 kartki</option>
                    <option>Cyrkiel</option>
                    <option>Linijka 30 cm</option>
                    <option>Ekierka</option>
                    <option>Linijka 50 cm</option>
                </select><br>
                liczba sztuk: <input type="number" name="quantity" value="0" id="quantity"><br>
                <input type="submit" value="OBLICZ">
            </form>
    <?php
    if (isset($_POST['product'])) {
        $product = $_POST['product'];
        $quantity = $_POST['quantity'];
        $result = mysqli_query($connection, "SELECT cena FROM towary WHERE nazwa = '$product';");
        $row = mysqli_fetch_row($result);
        $total = round($row[0] * $quantity, 1);
        echo 'Wartość zakupów: ' . $total . ' zł';
    }
    ?>
        </section>
        <section id="middle">
            <img src="zakupy2.png" alt="hurtownia">
            <h4>Kontakt</h4>
            <p>telefon: 888999777<br>e-mail: <a href="mailto:[email protected]">[email protected]</a></p>
        </section>
        <section id="right">
            <h4>Ceny wybranych artykułów w hurtowni:</h4>
            <table>
    <?php
    $result = mysqli_query($connection, 'SELECT nazwa, cena FROM towary LIMIT 4;');
    while ($row = mysqli_fetch_row($result)) {
        echo '<tr><td>' . $row[0] . '</td><td>' . $row[1] . '</td></tr>';
    }
    ?>
            </table>
        </section>
        <footer>
            <h2>Witrynę wykonał Bartosz Bryniarski</h2>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (index.php)
  42. Krok 42: Zamknięcie połączenia z bazą

    Kryteria:

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

    ok. 2 min
    Polecenie z arkusza

    Na końcu działania skrypt zamyka połączenie z serwerem

    Skrypt 2 stoi w panelu lewym, a skrypt 1 w prawym - serwer wykonuje kod PHP w kolejności, w jakiej stoi w pliku, więc skrypt 1 działa jako ostatni. Dlatego mysqli_close($connection) stoi na końcu skryptu 1, po pętli - to ostatnia operacja na bazie, także przy pierwszym wejściu na stronę (R.5.3). Strona spełnia wszystkie kryteria arkusza. Dalej dwa kroki o zabezpieczeniach - klucz ich nie wymaga.

    Typowe błędy

    mysqli_close na końcu skryptu 2 (pod formularzem) zamknie połączenie, zanim skrypt 1 w panelu prawym wyśle zapytanie - PHP 8 przerywa wtedy stronę błędem „mysqli object is already closed” i tabela zostaje pusta.

    index.php PHP zmienione: 1 linia
    <?php
    $connection = mysqli_connect('localhost', 'root', '', 'sklep');
    ?>
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <title>Artykuły biurowe</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <header>
            <h1>W naszej hurtowni kupisz najtaniej</h1>
        </header>
        <section id="left">
            <h4>Ile będą kosztować Twoje zakupy?</h4>
            <form method="post">
                wybierz artykuł
                <select name="product">
                    <option>Zeszyt 60 kartek</option>
                    <option>Zeszyt 32 kartki</option>
                    <option>Cyrkiel</option>
                    <option>Linijka 30 cm</option>
                    <option>Ekierka</option>
                    <option>Linijka 50 cm</option>
                </select><br>
                liczba sztuk: <input type="number" name="quantity" value="0" id="quantity"><br>
                <input type="submit" value="OBLICZ">
            </form>
    <?php
    if (isset($_POST['product'])) {
        $product = $_POST['product'];
        $quantity = $_POST['quantity'];
        $result = mysqli_query($connection, "SELECT cena FROM towary WHERE nazwa = '$product';");
        $row = mysqli_fetch_row($result);
        $total = round($row[0] * $quantity, 1);
        echo 'Wartość zakupów: ' . $total . ' zł';
    }
    ?>
        </section>
        <section id="middle">
            <img src="zakupy2.png" alt="hurtownia">
            <h4>Kontakt</h4>
            <p>telefon: 888999777<br>e-mail: <a href="mailto:[email protected]">[email protected]</a></p>
        </section>
        <section id="right">
            <h4>Ceny wybranych artykułów w hurtowni:</h4>
            <table>
    <?php
    $result = mysqli_query($connection, 'SELECT nazwa, cena FROM towary LIMIT 4;');
    while ($row = mysqli_fetch_row($result)) {
        echo '<tr><td>' . $row[0] . '</td><td>' . $row[1] . '</td></tr>';
    }
    mysqli_close($connection);
    ?>
            </table>
        </section>
        <footer>
            <h2>Witrynę wykonał Bartosz Bryniarski</h2>
        </footer>
    </body>
    </html>

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

  43. Etap 6: Dobre praktyki (poza kluczem)

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

    Krok 43: Zabezpieczenie: zapytanie przygotowane i liczba sztuk

    ok. 5 min
    Polecenie z arkusza

    Wysyła do bazy danych zapytanie 2 (z pliku kwerendy.txt), zmodyfikowane w ten sposób, że w sekcji warunku nazwa produktu jest zgodna z wyborem w liście rozwijalnej

    Formularz podsuwa sześć nazw i pole liczbowe, ale serwer dostaje dowolny tekst - formularz da się wysłać z innej strony albo zmienić narzędziami przeglądarki. Sprawdzone na wersji z poprzednich kroków:

    • artykuł x' OR '1'='1 zamienia warunek w nazwa = 'x' OR '1'='1', prawdziwy dla każdego wiersza - 2 „sztuki” dają „Wartość zakupów: 9 zł”, czyli cenę pierwszego zeszytu. To SQL injection,
    • puste pole liczby sztuk (wystarczy skasować zero) - PHP 8 nie mnoży liczby przez pusty napis i zamiast strony pokazuje „Fatal error: Uncaught TypeError”,
    • liczba ujemna, np. -5 cyrkli, daje „Wartość zakupów: -62 zł”.

    Poprawki:

    • zapytanie przygotowane: mysqli_prepare ze znakiem ? w miejscu nazwy, mysqli_stmt_bind_param z typem 's', mysqli_stmt_execute i mysqli_stmt_get_result - baza dostaje dane osobno od treści zapytania,
    • (int) zamienia wpis na liczbę całkowitą (pusty napis to 0), a warunek $row && $quantity >= 0 liczy kwotę tylko dla znalezionego artykułu i nieujemnej liczby sztuk.

    Podgląd: ten sam artykuł x' OR '1'='1 nie daje już żadnej kwoty. Stare linie zostają w komentarzu.

    Typowe błędy

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

    index.php PHP zmienione: 11 linii
    <?php
    $connection = mysqli_connect('localhost', 'root', '', 'sklep');
    ?>
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <title>Artykuły biurowe</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <header>
            <h1>W naszej hurtowni kupisz najtaniej</h1>
        </header>
        <section id="left">
            <h4>Ile będą kosztować Twoje zakupy?</h4>
            <form method="post">
                wybierz artykuł
                <select name="product">
                    <option>Zeszyt 60 kartek</option>
                    <option>Zeszyt 32 kartki</option>
                    <option>Cyrkiel</option>
                    <option>Linijka 30 cm</option>
                    <option>Ekierka</option>
                    <option>Linijka 50 cm</option>
                </select><br>
                liczba sztuk: <input type="number" name="quantity" value="0" id="quantity"><br>
                <input type="submit" value="OBLICZ">
            </form>
    <?php
    if (isset($_POST['product'])) {
        $product = $_POST['product'];
        // $quantity = $_POST['quantity'];
        $quantity = (int) $_POST['quantity'];
        // $result = mysqli_query($connection, "SELECT cena FROM towary WHERE nazwa = '$product';");
        $statement = mysqli_prepare($connection, 'SELECT cena FROM towary WHERE nazwa = ?;');
        mysqli_stmt_bind_param($statement, 's', $product);
        mysqli_stmt_execute($statement);
        $result = mysqli_stmt_get_result($statement);
        $row = mysqli_fetch_row($result);
        if ($row && $quantity >= 0) {
            $total = round($row[0] * $quantity, 1);
            echo 'Wartość zakupów: ' . $total . ' zł';
        }
    }
    ?>
        </section>
        <section id="middle">
            <img src="zakupy2.png" alt="hurtownia">
            <h4>Kontakt</h4>
            <p>telefon: 888999777<br>e-mail: <a href="mailto:[email protected]">[email protected]</a></p>
        </section>
        <section id="right">
            <h4>Ceny wybranych artykułów w hurtowni:</h4>
            <table>
    <?php
    $result = mysqli_query($connection, 'SELECT nazwa, cena FROM towary LIMIT 4;');
    while ($row = mysqli_fetch_row($result)) {
        echo '<tr><td>' . $row[0] . '</td><td>' . $row[1] . '</td></tr>';
    }
    mysqli_close($connection);
    ?>
            </table>
        </section>
        <footer>
            <h2>Witrynę wykonał Bartosz Bryniarski</h2>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (index.php)
  44. Krok 44: Zabezpieczenie: dane z bazy na wyjściu

    ok. 2 min
    Polecenie z arkusza

    Wyświetla dane pobrane zapytaniem wewnątrz komórek tabeli. W lewej kolumnie tabeli wypisywane są nazwy czterech towarów, w prawej kolumnie tabeli – odpowiadające im ceny (zgodnie z obrazem 3)

    Nazwy towarów pochodzą z bazy, a bazę zapełnia ktoś inny niż skrypt. Gdyby w nazwie stał znacznik <script>, przeglądarka wykonałaby go u każdego, kto otworzy stronę. htmlspecialchars() zamienia <, >, & i cudzysłowy na encje, więc znaczniki wyświetlą się jako tekst. Wszystko, co wypisujesz z bazy lub z formularza, przechodzi przez htmlspecialchars.

    Podgląd bez zmian. Stare linie zostają w komentarzu; na egzaminie wystarczy wersja z kroku „Zamknięcie połączenia”.

    index.php PHP zmienione: 2 linie
    <?php
    $connection = mysqli_connect('localhost', 'root', '', 'sklep');
    ?>
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <title>Artykuły biurowe</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <header>
            <h1>W naszej hurtowni kupisz najtaniej</h1>
        </header>
        <section id="left">
            <h4>Ile będą kosztować Twoje zakupy?</h4>
            <form method="post">
                wybierz artykuł
                <select name="product">
                    <option>Zeszyt 60 kartek</option>
                    <option>Zeszyt 32 kartki</option>
                    <option>Cyrkiel</option>
                    <option>Linijka 30 cm</option>
                    <option>Ekierka</option>
                    <option>Linijka 50 cm</option>
                </select><br>
                liczba sztuk: <input type="number" name="quantity" value="0" id="quantity"><br>
                <input type="submit" value="OBLICZ">
            </form>
    <?php
    if (isset($_POST['product'])) {
        $product = $_POST['product'];
        // $quantity = $_POST['quantity'];
        $quantity = (int) $_POST['quantity'];
        // $result = mysqli_query($connection, "SELECT cena FROM towary WHERE nazwa = '$product';");
        $statement = mysqli_prepare($connection, 'SELECT cena FROM towary WHERE nazwa = ?;');
        mysqli_stmt_bind_param($statement, 's', $product);
        mysqli_stmt_execute($statement);
        $result = mysqli_stmt_get_result($statement);
        $row = mysqli_fetch_row($result);
        if ($row && $quantity >= 0) {
            $total = round($row[0] * $quantity, 1);
            echo 'Wartość zakupów: ' . $total . ' zł';
        }
    }
    ?>
        </section>
        <section id="middle">
            <img src="zakupy2.png" alt="hurtownia">
            <h4>Kontakt</h4>
            <p>telefon: 888999777<br>e-mail: <a href="mailto:[email protected]">[email protected]</a></p>
        </section>
        <section id="right">
            <h4>Ceny wybranych artykułów w hurtowni:</h4>
            <table>
    <?php
    $result = mysqli_query($connection, 'SELECT nazwa, cena FROM towary LIMIT 4;');
    while ($row = mysqli_fetch_row($result)) {
        // echo '<tr><td>' . $row[0] . '</td><td>' . $row[1] . '</td></tr>';
        echo '<tr><td>' . htmlspecialchars($row[0]) . '</td><td>' . htmlspecialchars($row[1]) . '</td></tr>';
    }
    mysqli_close($connection);
    ?>
            </table>
        </section>
        <footer>
            <h2>Witrynę wykonał Bartosz Bryniarski</h2>
        </footer>
    </body>
    </html>

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

  45. Etap 7: Oddanie pracy

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

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

    ok. 5 min
    Polecenie z arkusza

    Po zakończeniu pracy utwórz plik tekstowy. Zapisz w nim nazwę przeglądarki internetowej, w której weryfikowałeś poprawność działania witryny. Nazwij plik przeglądarka.txt i zapisz go w folderze z numerem PESEL. Nagraj płytę z rezultatami pracy.

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

    W folderze z numerem zdającego muszą być: przeglądarka.txt, import.jpg, kw1.jpg, kw2.jpg, kw3.jpg, kw4.jpg, kwerendy.txt, index.php, styl.css, zakupy.png, zakupy2.png - i może zostać rozpakowany sklep.sql. Nagraj płytę, sprawdź jej odczyt i opisz ją numerem zdającego.

    Typowe błędy

    Płyta, której nie da się odczytać, to zero punktów za wszystkie pięć rezultatów - sprawdź ją, zanim oddasz.

    przeglądarka.txt Tekst nowy plik
    Google Chrome

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

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