Przejdź do głównej treści
E.14-03-20.06-SGCzerwiec 2020 · 46 kroków · ok. 87 min · 36 kryteriów z klucza

Rozwiązanie krok po kroku: Kwiaciarnie i wyszukiwarka po mieście (Wersja podstawowa)

Strona o kwiatach z wyszukiwarką kwiaciarni: baza kwiaciarnia z dwiema tabelami (kwiaciarnie i zamowienia) utworzonymi kreatorem phpMyAdmin, trzy zapytania - wybór kwiaciarni z miasta, zamówienia z jednego dnia i zliczanie zamówień COUNT z GROUP BY - oraz eksport bazy do pliku. Do tego trzy zdjęcia kwiatów wykadrowane do kwadratu 190 × 190 px i zapisane w JPEG, dwie strony - index.html i znajdz.php - z banerem, dwoma panelami i stopką, style w styl.css i skrypt PHP, który po wpisaniu miejscowości w formularzu wypisuje nazwy i ulice kwiaciarni z tego miasta.

To arkusz E.14 z czerwca 2020 - kwalifikacji formuły 2012, którą zastąpiła INF.03. Kroki idą zdanie po zdaniu za treścią arkusza - przy każdym jest polecenie z arkusza, a kod pokazuje dokładnie te linie, które je spełniają. Skrypt jest najpierw napisany najprościej, funkcjami mysqli z tabeli 3 arkusza, a na końcu sprawdzony na prawdziwym wstrzyknięciu SQL i zabezpieczony.

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 i zabezpieczonym wypisywaniem danych - obie wersje są zgodne z kluczem.

Zdjęcia pochodzą z oryginalnego archiwum CKE egzamin3.zip (załącznik do pobrania na stronie arkusza, hasło w treści zadania). Tabele i zapytania są wykonane 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 36 kryteriów (R.1.1 - R.5.5), każde za 1 punkt. Próg zdania części praktycznej to 75%, czyli 27 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-10 · po tym etapie masz 9 z 36 kryteriów (pkt)

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

    ok. 2 min
    Polecenie z arkusza

    Aby wykonać zadanie zaloguj się bez hasła na konto Egzamin. Na pulpicie znajduje się plik egzamin3.zip, zabezpieczony hasłem 5T2k@W$2n Na pulpicie utwórz folder i nazwij go Twoim numerem PESEL. Wszystkie pliki utworzone w czasie egzaminu umieść 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 egzamin3.zip otwierasz programem 7-Zip (albo Eksploratorem Windows) i rozpakowujesz, podając hasło 5T2k@W$2n - wielkość liter i znaki @ oraz $ mają znaczenie. W środku jest folder egzamin z trzema zdjęciami: gerbera.png, gozdzik.png, roza.png i plikiem kwiaty_zrodlo.txt z adresami, skąd pochodzą zdjęcia.

    Do folderu z numerem PESEL trafia wszystko, co powstanie: zrzuty, kwerendy.txt, eksport bazy, grafiki, strony i styl.

    Typowe błędy

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

  2. Krok 2: XAMPP i baza kwiaciarnia

    ok. 2 min
    Polecenie z arkusza

    Za pomocą wizualnych elementów (kreatorów) przystawki phpMyAdmin programu XAMPP utwórz bazę danych według wytycznych: Nazwa bazy kwiaciarnia

    W XAMPP Control Panel klikasz Start przy Apache i MySQL, potem w przeglądarce otwierasz http://localhost/phpmyadmin. W lewym panelu Nowa, nazwa kwiaciarnia, porównywanie np. utf8mb4_polish_ci (arkusz go nie narzuca, a polskie porównywanie dobrze sortuje „róża” i „goździk”), Utwórz.

    Arkusz wymaga kreatorów, czyli formularzy phpMyAdmin, a nie pisania CREATE TABLE na karcie SQL. phpMyAdmin i tak zamienia każdy formularz na zapytanie SQL i pokazuje je po wykonaniu - w kolejnych krokach to zapytanie jest pokazane, żeby było widać, co dokładnie powstaje.

    Typowe błędy

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

  3. Krok 3: Tabela kwiaciarnie z kluczem id_kwiaciarni

    Kryteria:

    R.1.4 Tabela kwiaciarnie ma pola nazwa, miasto i ulica dowolnego typu tekstowego

    ok. 3 min
    Polecenie z arkusza

    Tabela kwiaciarnie z autonumerowanym kluczem podstawowym id_kwiaciarni

    Zaznacz bazę kwiaciarnia, w polu Utwórz tabelę wpisz nazwę kwiaciarnie i liczbę kolumn 4, Wykonaj. W formularzu kolumn (nazwy i typy z tabeli 1 arkusza):

    • id_kwiaciarni - typ INT, w kolumnie Indeks wybierz PRIMARY, zaznacz A_I (AUTO_INCREMENT, autonumerowanie),
    • nazwa, miasto, ulica - typ VARCHAR, długość np. 50.

    Zapisz. phpMyAdmin wykonuje zapytanie:

    CREATE TABLE kwiaciarnie (
        id_kwiaciarni INT NOT NULL AUTO_INCREMENT,
        nazwa VARCHAR(50),
        miasto VARCHAR(50),
        ulica VARCHAR(50),
        PRIMARY KEY (id_kwiaciarni)
    );
    

    Pola nazwa, miasto, ulica są tekstowe, jak wymaga klucz (R.1.4).

    Typowe błędy

    Bez zaznaczonego A_I klucz nie jest autonumerowany - przy dodawaniu danych trzeba by wpisywać numery ręcznie, a kryterium R.1.2 przepada.

  4. Krok 4: Tabela zamowienia z kluczem id_zam

    Kryteria: ,

    R.1.2 Tabela kwiaciarnie ma klucz podstawowy id_kwiaciarni oraz tabela zamowienia ma klucz podstawowy id_zam, oba klucze są autoinkrementowane

    R.1.3 Tabela zamowienia ma pola: id_kwiaciarni dowolnego typu całkowitego, data typu date, kwiaty typu tekstowego i cena dowolnego typu liczbowego

    ok. 3 min
    Polecenie z arkusza

    Tabela zamowienia z autonumerowanym kluczem podstawowym id_zam. Pola oraz dane obu tabel znajdują się w tabelach 1 i 2, należy je wprowadzić do tabel

    Druga tabela, zamowienia, z pięcioma kolumnami z tabeli 2 arkusza:

    • id_zam - INT, PRIMARY, A_I,
    • id_kwiaciarni - INT: numer kwiaciarni z tabeli kwiaciarnie, która przyjęła zamówienie,
    • data - typ DATE, bo klucz wymaga typu daty (R.1.3),
    • kwiaty - VARCHAR(50),
    • cena - INT (ceny w tabeli są całkowite; klucz przyjmuje dowolny typ liczbowy).
    CREATE TABLE zamowienia (
        id_zam INT NOT NULL AUTO_INCREMENT,
        id_kwiaciarni INT,
        data DATE,
        kwiaty VARCHAR(50),
        cena INT,
        PRIMARY KEY (id_zam)
    );
    

    Obie tabele mają autonumerowane klucze podstawowe (R.1.2), a pola zamowienia mają typy z klucza (R.1.3).

    Typowe błędy

    Data w kolumnie typu VARCHAR wygląda tak samo, ale klucz wymaga typu date (R.1.3), a porównanie napisów „16.01.2017” z datą w zapytaniu 2 nie zadziała.

  5. Krok 5: Dane tabeli kwiaciarnie

    ok. 2 min
    Polecenie z arkusza

    Pola oraz dane obu tabel znajdują się w tabelach 1 i 2, należy je wprowadzić do tabel

    Tabela kwiaciarnie, karta Wstaw: dwa wiersze z tabeli 1 arkusza. Pole id_kwiaciarni możesz zostawić puste - numer nada autonumerowanie (1, 2), tak jak w arkuszu. phpMyAdmin wykonuje:

    INSERT INTO kwiaciarnie (id_kwiaciarni, nazwa, miasto, ulica) VALUES
    (1, 'Astra', 'Warszawa', 'Sobieskiego'),
    (2, 'Melisa', 'Malbork', 'Konopnickiej');
    

    Podgląd: karta Przeglądaj po wstawieniu - Astra w Warszawie i Melisa w Malborku.

    Podgląd strony po tym kroku
    Podgląd strony po kroku 5
  6. Krok 6: Dane tabeli zamowienia

    Kryteria:

    R.1.5 Tabele zamowienia i kwiaciarnie wypełniono zgodnie z tabelą 1 i 2 arkusza

    ok. 4 min
    Polecenie z arkusza

    Pola oraz dane obu tabel znajdują się w tabelach 1 i 2, należy je wprowadzić do tabel

    Sześć zamówień z tabeli 2. Pole typu DATE przyjmuje datę w formacie RRRR-MM-DD, więc „16.01.2017” z arkusza wpisujesz jako 2017-01-16 (phpMyAdmin przy polu daty pokazuje też kalendarz do wyboru dnia). Kwiaty z polskimi literami - „róża”, „goździk” - tak jak w arkuszu.

    INSERT INTO zamowienia (id_zam, id_kwiaciarni, data, kwiaty, cena) VALUES
    (1, 1, '2017-01-16', 'róża', 250),
    (2, 1, '2017-01-10', 'gerbera', 120),
    (3, 2, '2017-01-06', 'róża', 200),
    (4, 2, '2017-01-09', 'goździk', 170),
    (5, 1, '2017-01-07', 'róża', 125),
    (6, 1, '2017-01-11', 'róża', 75);
    

    Obie tabele są wypełnione zgodnie z arkuszem (R.1.5). Kwiaciarnia 1 (Astra) ma cztery zamówienia, kwiaciarnia 2 (Melisa) - dwa; to przyda się przy zapytaniu 3.

    Typowe błędy

    Data wpisana po polsku 16.01.2017 w pole DATE zostanie odrzucona albo zamieniona na 0000-00-00 - wtedy zapytanie 2 nic nie znajdzie.

    Podgląd strony po tym kroku
    Podgląd strony po kroku 6
  7. Krok 7: Kwerenda 1: kwiaciarnie z Malborka

    Kryteria: ,

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

    R.1.7 Zapisano zapytanie 1 wybierające jedynie pole nazwa i ulica dla kwiaciarni z miasta Malbork. W pliku z kwerendami lub na zrzucie istnieje zapis np.: SELECT nazwa, ulica FROM kwiaciarnie WHERE miasto="Malbork"; oraz na zrzucie ekranu widoczne są jedynie dwa pola: nazwa, ulica; wartości Melisa, Konopnickiej

    ok. 3 min
    Polecenie z arkusza

    Kwerenda 1: wybierająca jedynie pole nazwa i ulica dla kwiaciarni z miasta Malbork

    Karta SQL bazy kwiaciarnia. Zapytanie klauzula po klauzuli:

    • SELECT nazwa, ulica - „jedynie” te dwa pola, bez *,
    • FROM kwiaciarnie - z tabeli kwiaciarni,
    • WHERE miasto = 'Malbork' - tylko wiersze, w których miasto to Malbork; napis w apostrofach.

    Wynik: jeden wiersz Melisa, Konopnickiej - dokładnie ten, który pokazuje obraz 2 arkusza. Zapytanie kopiujesz do pliku kwerendy.txt w folderze zdającego (R.1.6), a cały ekran z wynikiem zapisujesz jako kw1.jpg (Print Screen, wklejenie do edytora grafiki, eksport do JPEG).

    To zapytanie wykona później skrypt - w miejsce 'Malbork' wstawi miejscowość wpisaną w formularzu.

    Typowe błędy

    Zrzuty mają być w JPEG i obejmować cały ekran z paskiem zadań - wykadrowanego zrzutu egzaminator nie ocenia (uwaga przy R.1 w kluczu).

    kwerendy.txt Tekst nowy plik
    -- Kwerenda 1
    SELECT nazwa, ulica FROM kwiaciarnie WHERE miasto = 'Malbork';
    Podgląd strony po tym kroku
    Podgląd strony po kroku 7
  8. Krok 8: Kwerenda 2: zamówienie z 7 stycznia 2017

    Kryteria:

    R.1.8 Zapisano zapytanie 2 wybierające jedynie id zamówienia, złożonego z datą 7 stycznia 2017 r. W pliku z kwerendami lub na zrzucie istnieje zapis np.: SELECT id_zam FROM zamowienia WHERE data="2017.01.07"; oraz na zrzucie ekranu widoczne jest jedynie pole id_zam z jedną wartością: 5

    ok. 2 min
    Polecenie z arkusza

    Kwerenda 2: wybierająca jedynie id zamówienia, złożonego z datą 7 stycznia 2017 r.

    • SELECT id_zam - sam identyfikator zamówienia,
    • FROM zamowienia,
    • WHERE data = '2017-01-07' - datę w zapytaniu zapisujesz tak jak w polu DATE: rok, miesiąc, dzień.

    Wynik: jedno zamówienie o numerze 5 (róże za 125 zł w kwiaciarni Astra). Zrzut: kw2.jpg. Klucz pokazuje zapis "2017.01.07" z kropkami - MariaDB też go przyjmuje, bo w dacie traktuje każdy znak interpunkcyjny jako separator; zapis z myślnikami jest standardowy.

    Typowe błędy

    Kolejność „dzień.miesiąc.rok” ('07.01.2017') nie zadziała - baza odczyta ją jako rok 7, więc wynik będzie pusty.

    kwerendy.txt Tekst zmienione: 3 linie
    -- Kwerenda 1
    SELECT nazwa, ulica FROM kwiaciarnie WHERE miasto = 'Malbork';
    
    -- Kwerenda 2
    SELECT id_zam FROM zamowienia WHERE data = '2017-01-07';
    Podgląd strony po tym kroku
    Podgląd strony po kroku 8
  9. Krok 9: Kwerenda 3: liczba zamówień każdej kwiaciarni

    Kryteria:

    R.1.9 Zapisano zapytanie 3 wybierające jedynie pole id_kwiaciarni oraz liczące liczbę zamówień (wierszy) dla poszczególnych kwiaciarni. W pliku z kwerendami lub na zrzucie istnieje zapis np.: SELECT id_kwiaciarni, COUNT(id_kwiaciarni) FROM zamowienia GROUP BY id_kwiaciarni; oraz na zrzucie ekranu widoczne są dwa wiersze o wartościach 1, 4 oraz 2, 2; odpowiadają one polom id_kwiaciarni i policzonej liczbie kwiaciarni

    ok. 3 min
    Polecenie z arkusza

    Kwerenda 3: wybierająca jedynie pole id_kwiaciarni oraz licząca liczbę zamówień (wierszy) dla poszczególnych kwiaciarni

    • SELECT id_kwiaciarni, COUNT(*) - numer kwiaciarni i liczba wierszy,
    • FROM zamowienia,
    • GROUP BY id_kwiaciarni - wiersze z tym samym numerem kwiaciarni tworzą jedną grupę, a COUNT(*) liczy wiersze w każdej grupie osobno.

    Wynik: dwa wiersze - 1, 4 i 2, 2 (zgodnie z kluczem). Zrzut: kw3.jpg. Plik kwerendy.txt ma komplet trzech kwerend.

    Typowe błędy

    Bez GROUP BY COUNT(*) zlicza całą tabelę naraz i zwraca jeden wiersz z liczbą 6 - a „dla poszczególnych kwiaciarni” wymaga podziału na grupy.

    kwerendy.txt Tekst zmienione: 3 linie
    -- Kwerenda 1
    SELECT nazwa, ulica FROM kwiaciarnie WHERE miasto = 'Malbork';
    
    -- Kwerenda 2
    SELECT id_zam FROM zamowienia WHERE data = '2017-01-07';
    
    -- Kwerenda 3
    SELECT id_kwiaciarni, COUNT(*) FROM zamowienia GROUP BY id_kwiaciarni;
    Podgląd strony po tym kroku
    Podgląd strony po kroku 9
  10. Krok 10: Eksport bazy do pliku kwiaciarnia.sql

    Kryteria:

    R.1.1 Wykonano eksport bazy lub tabel z bazy do pliku kwiaciarnia.sql . Czas generowania wpisany w nagłówku pliku jest zgodny z datą i godziną egzaminu

    ok. 2 min
    Polecenie z arkusza

    Wyeksportuj tabele bazy danych do pliku kwiaciarnia.sql

    Zaznacz bazę kwiaciarnia (nie pojedynczą tabelę), karta Eksport, metoda Szybka, format SQL, Wykonaj. Przeglądarka pobiera plik kwiaciarnia.sql - przenosisz go do folderu zdającego. W pliku są obie tabele: polecenia CREATE TABLE z typami i kluczami oraz INSERT INTO z danymi. Na tej podstawie egzaminator ocenia kryteria R.1.2 - R.1.5, a w nagłówku pliku phpMyAdmin wpisuje czas generowania - musi się zgadzać z datą i godziną egzaminu (R.1.1).

    Plik kwiaciarnia.sql w archiwum tego rozwiązania wyeksportowano z tej samej bazy narzędziem mysqldump - struktura i dane są takie same, inny jest tylko nagłówek (bez linii „Czas generowania” z phpMyAdmina).

    Typowe błędy

    Eksport zrobiony przed wprowadzeniem danych albo po próbach w domu ma zły czas generowania lub braki w danych - eksportuj na końcu operacji na bazie, na egzaminie.

    kwiaciarnia.sql SQL nowy plik
    -- MariaDB dump 10.19  Distrib 10.4.27-MariaDB, for Win64 (AMD64)
    --
    -- Host: localhost    Database: kwiaciarnia
    -- ------------------------------------------------------
    -- Server version	10.4.27-MariaDB
    
    /*!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 */;
    /*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */;
    /*!40103 SET TIME_ZONE='+00:00' */;
    /*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
    /*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
    /*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
    /*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;
    
    --
    -- Table structure for table `kwiaciarnie`
    --
    
    DROP TABLE IF EXISTS `kwiaciarnie`;
    /*!40101 SET @saved_cs_client     = @@character_set_client */;
    /*!40101 SET character_set_client = utf8 */;
    CREATE TABLE `kwiaciarnie` (
      `id_kwiaciarni` int(11) NOT NULL AUTO_INCREMENT,
      `nazwa` varchar(50) DEFAULT NULL,
      `miasto` varchar(50) DEFAULT NULL,
      `ulica` varchar(50) DEFAULT NULL,
      PRIMARY KEY (`id_kwiaciarni`)
    ) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_polish_ci;
    /*!40101 SET character_set_client = @saved_cs_client */;
    
    --
    -- Dumping data for table `kwiaciarnie`
    --
    
    LOCK TABLES `kwiaciarnie` WRITE;
    /*!40000 ALTER TABLE `kwiaciarnie` DISABLE KEYS */;
    INSERT INTO `kwiaciarnie` VALUES (1,'Astra','Warszawa','Sobieskiego'),(2,'Melisa','Malbork','Konopnickiej');
    /*!40000 ALTER TABLE `kwiaciarnie` ENABLE KEYS */;
    UNLOCK TABLES;
    
    --
    -- Table structure for table `zamowienia`
    --
    
    DROP TABLE IF EXISTS `zamowienia`;
    /*!40101 SET @saved_cs_client     = @@character_set_client */;
    /*!40101 SET character_set_client = utf8 */;
    CREATE TABLE `zamowienia` (
      `id_zam` int(11) NOT NULL AUTO_INCREMENT,
      `id_kwiaciarni` int(11) DEFAULT NULL,
      `data` date DEFAULT NULL,
      `kwiaty` varchar(50) DEFAULT NULL,
      `cena` int(11) DEFAULT NULL,
      PRIMARY KEY (`id_zam`)
    ) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_polish_ci;
    /*!40101 SET character_set_client = @saved_cs_client */;
    
    --
    -- Dumping data for table `zamowienia`
    --
    
    LOCK TABLES `zamowienia` WRITE;
    /*!40000 ALTER TABLE `zamowienia` DISABLE KEYS */;
    INSERT INTO `zamowienia` VALUES (1,1,'2017-01-16','róża',250),(2,1,'2017-01-10','gerbera',120),(3,2,'2017-01-06','róża',200),(4,2,'2017-01-09','goździk',170),(5,1,'2017-01-07','róża',125),(6,1,'2017-01-11','róża',75);
    /*!40000 ALTER TABLE `zamowienia` ENABLE KEYS */;
    UNLOCK TABLES;
    /*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */;
    
    /*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
    /*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;
    /*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */;
    /*!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 */;
    /*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;
    
    -- Dump completed
  11. Etap 2: Grafika

    Kroki 11-13 · po tym etapie masz 10 z 36 kryteriów (pkt)

    Krok 11: Kadrowanie zdjęć do proporcji 1:1

    ok. 4 min
    Polecenie z arkusza

    Wytyczne odnośnie grafiki zapisanej w plikach roza.png, gerbera.png, gozdzik.png: obrazy przycięte (wykadrowane) do proporcji 1:1

    Zdjęcia nie są kwadratowe: gerbera.png ma 640 × 560 px, roza.png i gozdzik.png - 640 × 426 px. Kadrowanie 1:1 to wycięcie kwadratu o boku równym krótszemu bokowi. W GIMP-ie: narzędzie Kadrowanie (Shift+C), w opcjach narzędzia zaznacz Stały: Proporcje i wpisz 1:1, zaznacz cały obraz i przesuń kadr na środek, Enter. Kwadraty mają 560 × 560 px (gerbera) i 426 × 426 px (róża, goździk).

    Podgląd: róża po wykadrowaniu ze środka zdjęcia.

    Typowe błędy

    Zmiana rozmiaru do 190 × 190 bez kadrowania spłaszcza zdjęcie (proporcje 3:2 wciśnięte w kwadrat) - klucz wymaga zachowania proporcji 1:1.

    Podgląd strony po tym kroku
    Podgląd strony po kroku 11
  12. Krok 12: Rozmiar 190 × 190 px

    ok. 2 min
    Polecenie z arkusza

    rozmiar 190 px na 190 px

    Obraz → Skaluj obraz, przy zamkniętym łańcuchu proporcji wpisz szerokość 190 px - wysokość też wyjdzie 190, bo obraz jest już kwadratem. Tak samo dla wszystkich trzech zdjęć.

    Podgląd strony po tym kroku
    Podgląd strony po kroku 12
  13. Krok 13: Zapis w formacie JPEG

    Kryteria:

    R.2.1 Zapisano przynajmniej jeden obraz z roza, gerbera, gozdzik w formacie JPEG, o rozmiarze 190 px na 190 px (± 2 px, zachowując proporcję 1:1)

    ok. 2 min
    Polecenie z arkusza

    format JPEG

    Plik → Eksportuj jako, nazwy gerbera.jpg, gozdzik.jpg, roza.jpg (rozszerzenie .jpg decyduje o formacie), jakość np. 90, Eksportuj. Zwykłe Zapisz w GIMP-ie tworzy plik .xcf. JPEG nie ma przezroczystości, ale zdjęcia jej nie miały - wszystkie piksele są nieprzezroczyste. Trzy obrazy 190 × 190 px w JPEG spełniają R.2.1.

    Typowe błędy

    Pliki muszą mieć nazwy bez polskich liter, dokładnie takie jak w arkuszu - strona odwołuje się do gozdzik.jpg, a nie do goździk.jpg.

    Podgląd strony po tym kroku
    Podgląd strony po kroku 13
  14. Etap 3: Strona index.html

    Kroki 14-26 · po tym etapie masz 18 z 36 kryteriów (pkt)

    Krok 14: Plik index.html

    ok. 1 min
    Polecenie z arkusza

    Witryna internetowa składa się ze stron index.html i znajdz.php.

    Najpierw powstaje cała strona index.html, a druga strona będzie jej kopią ze zmienionym panelem prawym - obie mają te same elementy wspólne. <!DOCTYPE html> oznacza HTML5, lang="pl" mówi przeglądarce, że treść jest po polsku.

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

    ok. 1 min
    Polecenie z arkusza

    Standard kodowania polskich znaków

    <meta charset="UTF-8"> jako pierwsza rzecz w <head>; plik zapisz w edytorze w kodowaniu UTF-8. Bez tego „Goździk” i „Znajdź kwiaciarnię” mogą wyświetlić się z krzakami.

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

    Kryteria:

    R.2.3 Nadano tytuł przynajmniej jednej stronie "Kwiaty”

    ok. 1 min
    Polecenie z arkusza

    Tytuł strony: „Kwiaty”

    <title>Kwiaty</title> w <head> - napis na karcie przeglądarki (R.2.3). Nie myl go z nagłówkiem banera „Moje kwiaty”.

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

    Kryteria:

    R.3.5 Przynajmniej jedna strona zawiera działające połączenie z zewnętrznym arkuszem stylów o nazwie styl.css formatowanie pochodzi jedynie od pliku CSS. 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

    Połączenie z zewnętrznym arkuszem stylów o nazwie styl.css

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

    index.html HTML zmienione: 1 linia
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <title>Kwiaty</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
    </body>
    </html>
    Podgląd strony po tym kroku (index.html)
  18. Krok 18: Bloki: baner, panel lewy, panel prawy i stopka

    Kryteria:

    R.2.4 Układ przynajmniej jednej strony zdefiniowano dzieląc ją na bloki: baner, panel lewy i prawy oraz stopkę za pomocą znaczników sekcji

    ok. 2 min
    Polecenie z arkusza

    Podział strony na bloki: baner, panel lewy i prawy oraz stopkę za pomocą znaczników sekcji

    Baner to znacznik <header>, stopka <footer>, a dwa panele - znaczniki <section> z identyfikatorami left i right (R.2.4). Identyfikatory przydadzą się w CSS: panele różnią się kolorem i szerokością, więc każdy dostaje własną regułę #left, #right.

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

    ok. 1 min
    Polecenie z arkusza

    Zawartość banera: nagłówek pierwszego stopnia o treści: „Moje kwiaty”

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

    index.html HTML zmienione: 1 linia
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <title>Kwiaty</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <header>
            <h1>Moje kwiaty</h1>
        </header>
        <section id="left">
        </section>
        <section id="right">
        </section>
        <footer>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (index.html)
  20. Krok 20: Panel lewy: nagłówek trzeciego stopnia

    ok. 1 min
    Polecenie z arkusza

    Zawartość panelu lewego: Nagłówek trzeciego stopnia o treści: „Kwiaty dla Ciebie!”

    <h3> - nagłówek trzeciego stopnia. Na stronie nie ma <h2>, ale arkusz narzuca stopień nagłówka, więc zostaje h3.

    index.html HTML zmienione: 1 linia
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <title>Kwiaty</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <header>
            <h1>Moje kwiaty</h1>
        </header>
        <section id="left">
            <h3>Kwiaty dla Ciebie!</h3>
        </section>
        <section id="right">
        </section>
        <footer>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (index.html)
  21. Krok 21: Odnośnik „Rozpoznaj kwiaty”

    Kryteria:

    R.3.4 Na przynajmniej jednej stronie wybranie odnośnika o treści „Rozpoznaj kwiaty” prowadzi do strony https://www.swiatkwiatow.pl/

    ok. 1 min
    Polecenie z arkusza

    Odnośnik o treści „Rozpoznaj kwiaty” prowadzący do strony „https://www.swiatkwiatow.pl/”

    <a href="https://www.swiatkwiatow.pl/"> - pełny adres z https://, bo to strona w innym serwisie (R.3.4). Odnośnik jest elementem liniowym, więc następny stanąłby obok w tym samym wierszu; <br> przenosi kolejny element do nowej linii, jak na obrazie 1.

    Typowe błędy

    Adres bez https:// (www.swiatkwiatow.pl) przeglądarka potraktuje jak plik w folderze strony i pokaże błąd 404.

    index.html HTML zmienione: 1 linia
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <title>Kwiaty</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <header>
            <h1>Moje kwiaty</h1>
        </header>
        <section id="left">
            <h3>Kwiaty dla Ciebie!</h3>
            <a href="https://www.swiatkwiatow.pl/">Rozpoznaj kwiaty</a><br>
        </section>
        <section id="right">
        </section>
        <footer>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (index.html)
  22. Krok 22: Odnośnik „Znajdź kwiaciarnię”

    Kryteria:

    R.3.3 Na przynajmniej jednej stronie wybranie odnośnika o treści „Znajdź kwiaciarnię” prowadzi do strony znajdz.php

    ok. 1 min
    Polecenie z arkusza

    Poniżej odnośnik o treści „Znajdź kwiaciarnię” prowadzący do pliku znajdz.php

    href="znajdz.php" - ścieżka względna, sama nazwa pliku z tego samego folderu. Klucz przy R.3.3 zastrzega, że odsyłacz musi zawierać ścieżkę względną. Plik znajdz.php powstanie za chwilę, a otwarty przez http://localhost/… wykona skrypt PHP.

    Typowe błędy

    Ścieżka bezwzględna (C:/Users/.../znajdz.php albo http://localhost/znajdz.php) przestaje działać po skopiowaniu folderu na płytę i u egzaminatora.

    index.html HTML zmienione: 1 linia
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <title>Kwiaty</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <header>
            <h1>Moje kwiaty</h1>
        </header>
        <section id="left">
            <h3>Kwiaty dla Ciebie!</h3>
            <a href="https://www.swiatkwiatow.pl/">Rozpoznaj kwiaty</a><br>
            <a href="znajdz.php">Znajdź kwiaciarnię</a><br>
        </section>
        <section id="right">
        </section>
        <footer>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (index.html)
  23. Krok 23: Panel lewy: obraz goździka

    Kryteria:

    R.2.6 Na przynajmniej jednej stronie w bloku lewym umieszczono obraz gozdzik z tekstem alternatywnym „Goździk"

    ok. 1 min
    Polecenie z arkusza

    Poniżej obraz gozdzik.jpg z tekstem alternatywnym „Goździk”

    src - plik po kadrowaniu, alt - tekst, który przeczyta czytnik ekranu albo pokaże przeglądarka, gdy obraz się nie wczyta (R.2.6). Ten sam plik wróci w panelu prawym; rozmiar 180 px tylko dla tego obrazu ustawi CSS.

    index.html HTML zmienione: 1 linia
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <title>Kwiaty</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <header>
            <h1>Moje kwiaty</h1>
        </header>
        <section id="left">
            <h3>Kwiaty dla Ciebie!</h3>
            <a href="https://www.swiatkwiatow.pl/">Rozpoznaj kwiaty</a><br>
            <a href="znajdz.php">Znajdź kwiaciarnię</a><br>
            <img src="gozdzik.jpg" alt="Goździk">
        </section>
        <section id="right">
        </section>
        <footer>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (index.html)
  24. Krok 24: Stopka: autor strony

    ok. 1 min
    Polecenie z arkusza

    Zawartość stopki: nagłówek trzeciego stopnia o treści: „Stronę opracował:”, dalej wstawiony numer PESEL zdającego

    Drugi <h3> na stronie. Na egzaminie po dwukropku wpisujesz swój numer PESEL; w tym rozwiązaniu w jego miejscu stoi imię i nazwisko autora: Bartosz Bryniarski.

    index.html HTML zmienione: 1 linia
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <title>Kwiaty</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <header>
            <h1>Moje kwiaty</h1>
        </header>
        <section id="left">
            <h3>Kwiaty dla Ciebie!</h3>
            <a href="https://www.swiatkwiatow.pl/">Rozpoznaj kwiaty</a><br>
            <a href="znajdz.php">Znajdź kwiaciarnię</a><br>
            <img src="gozdzik.jpg" alt="Goździk">
        </section>
        <section id="right">
        </section>
        <footer>
            <h3>Stronę opracował: Bartosz Bryniarski</h3>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (index.html)
  25. Krok 25: Panel prawy: trzy obrazy obok siebie

    Kryteria:

    R.2.7 Na przynajmniej jednej stronie w bloku prawym umieszczono trzy obrazy kwiatów z tekstem alternatywnym odpowiadającym nazwie kwiatu

    ok. 2 min
    Polecenie z arkusza

    Panel prawy dla strony index.html: Obok siebie trzy obrazy z gerberą, goździkiem, różą, tekst alternatywny to nazwa kwiatu

    Trzy znaczniki <img> jeden po drugim. Obraz jest elementem liniowym - stoją obok siebie w jednym wierszu, a przerwy między nimi to odstępy po znakach nowej linii w kodzie (jak na obrazie 1). Tekst alternatywny to nazwa kwiatu, z polskimi literami: „goździk”, „róża” (R.2.7).

    index.html HTML zmienione: 3 linie
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <title>Kwiaty</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <header>
            <h1>Moje kwiaty</h1>
        </header>
        <section id="left">
            <h3>Kwiaty dla Ciebie!</h3>
            <a href="https://www.swiatkwiatow.pl/">Rozpoznaj kwiaty</a><br>
            <a href="znajdz.php">Znajdź kwiaciarnię</a><br>
            <img src="gozdzik.jpg" alt="Goździk">
        </section>
        <section id="right">
            <img src="gerbera.jpg" alt="gerbera">
            <img src="gozdzik.jpg" alt="goździk">
            <img src="roza.jpg" alt="róża">
        </section>
        <footer>
            <h3>Stronę opracował: Bartosz Bryniarski</h3>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (index.html)
  26. Krok 26: Panel prawy: paragraf

    Kryteria:

    R.2.5 Zapisano na przynajmniej jednej stronie nagłówki: w banerze h1 "Moje kwiaty", w panelu lewym h3 "Kwiaty dla Ciebie!", w stopce h3 "Stronę opracował <PESEL>" oraz w panelu prawym paragraf (znacznik <p>)

    ok. 1 min
    Polecenie z arkusza

    Poniżej paragraf (akapit) o treści „Strona poświęcona miłośnikom kwiatów”

    Paragraf <p> - akapit jest blokiem, więc stoi pod obrazami. Nagłówki h1 w banerze, h3 w panelu lewym i w stopce oraz paragraf w panelu prawym dają R.2.5. Strona index.html jest gotowa - wygląd nada jej styl.

    index.html HTML zmienione: 1 linia
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <title>Kwiaty</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <header>
            <h1>Moje kwiaty</h1>
        </header>
        <section id="left">
            <h3>Kwiaty dla Ciebie!</h3>
            <a href="https://www.swiatkwiatow.pl/">Rozpoznaj kwiaty</a><br>
            <a href="znajdz.php">Znajdź kwiaciarnię</a><br>
            <img src="gozdzik.jpg" alt="Goździk">
        </section>
        <section id="right">
            <img src="gerbera.jpg" alt="gerbera">
            <img src="gozdzik.jpg" alt="goździk">
            <img src="roza.jpg" alt="róża">
            <p>Strona poświęcona miłośnikom kwiatów</p>
        </section>
        <footer>
            <h3>Stronę opracował: Bartosz Bryniarski</h3>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (index.html)
  27. Etap 4: Strona znajdz.php

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

    Krok 27: Plik znajdz.php: kopia index.html z nowym paragrafem

    Kryteria:

    R.2.2 Witrynę internetową zapisano w plikach index.html i znajdz.php oraz zastosowano właściwy standard kodowania polskich znaków na przynajmniej jednej stronie

    ok. 2 min
    Polecenie z arkusza

    Panel prawy dla strony znajdz.php: Obok siebie trzy obrazy z gerberą, goździkiem, różą, tekst alternatywny to nazwa kwiatu. Paragraf o treści: „Podaj miejscowość, w której poszukujesz kwiaciarni:”

    Kopiujesz index.html do pliku znajdz.php - baner, panel lewy, stopka i trzy obrazy są wspólne, więc wystarczy zmienić paragraf panelu prawego. Rozszerzenie .php, bo na tej stronie stanie skrypt. Obie strony mają kodowanie UTF-8 i nazwy z arkusza (R.2.2).

    Typowe błędy

    znajdz.html albo Znajdz.php to inna nazwa - odnośnik z panelu lewego prowadzi do znajdz.php, a serwer na Linuksie rozróżnia wielkość liter.

    znajdz.php PHP nowy plik
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <title>Kwiaty</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <header>
            <h1>Moje kwiaty</h1>
        </header>
        <section id="left">
            <h3>Kwiaty dla Ciebie!</h3>
            <a href="https://www.swiatkwiatow.pl/">Rozpoznaj kwiaty</a><br>
            <a href="znajdz.php">Znajdź kwiaciarnię</a><br>
            <img src="gozdzik.jpg" alt="Goździk">
        </section>
        <section id="right">
            <img src="gerbera.jpg" alt="gerbera">
            <img src="gozdzik.jpg" alt="goździk">
            <img src="roza.jpg" alt="róża">
            <p>Podaj miejscowość, w której poszukujesz kwiaciarni:</p>
        </section>
        <footer>
            <h3>Stronę opracował: Bartosz Bryniarski</h3>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (znajdz.php)
  28. Krok 28: Formularz wysyłający dane metodą post

    Kryteria:

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

    ok. 1 min
    Polecenie z arkusza

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

    method="post" - dane jadą w treści żądania, nie w adresie strony (R.3.2), action="znajdz.php" - do tego samego pliku (bez atrybutu action byłoby tak samo). Po wysłaniu przeglądarka wczyta znajdz.php jeszcze raz, a skrypt dostanie wpisaną miejscowość.

    znajdz.php PHP zmienione: 2 linie
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <title>Kwiaty</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <header>
            <h1>Moje kwiaty</h1>
        </header>
        <section id="left">
            <h3>Kwiaty dla Ciebie!</h3>
            <a href="https://www.swiatkwiatow.pl/">Rozpoznaj kwiaty</a><br>
            <a href="znajdz.php">Znajdź kwiaciarnię</a><br>
            <img src="gozdzik.jpg" alt="Goździk">
        </section>
        <section id="right">
            <img src="gerbera.jpg" alt="gerbera">
            <img src="gozdzik.jpg" alt="goździk">
            <img src="roza.jpg" alt="róża">
            <p>Podaj miejscowość, w której poszukujesz kwiaciarni:</p>
            <form method="post" action="znajdz.php">
            </form>
        </section>
        <footer>
            <h3>Stronę opracował: Bartosz Bryniarski</h3>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (znajdz.php)
  29. Krok 29: Pole edycyjne

    ok. 1 min
    Polecenie z arkusza

    zawierający: pole edycyjne

    <input type="text"> - jednowierszowe pole tekstowe. Atrybut name="city" to nazwa, pod którą wartość trafi do skryptu: $_POST['city']. Bez name przeglądarka w ogóle nie wysyła pola.

    znajdz.php PHP zmienione: 1 linia
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <title>Kwiaty</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <header>
            <h1>Moje kwiaty</h1>
        </header>
        <section id="left">
            <h3>Kwiaty dla Ciebie!</h3>
            <a href="https://www.swiatkwiatow.pl/">Rozpoznaj kwiaty</a><br>
            <a href="znajdz.php">Znajdź kwiaciarnię</a><br>
            <img src="gozdzik.jpg" alt="Goździk">
        </section>
        <section id="right">
            <img src="gerbera.jpg" alt="gerbera">
            <img src="gozdzik.jpg" alt="goździk">
            <img src="roza.jpg" alt="róża">
            <p>Podaj miejscowość, w której poszukujesz kwiaciarni:</p>
            <form method="post" action="znajdz.php">
                <input type="text" name="city">
            </form>
        </section>
        <footer>
            <h3>Stronę opracował: Bartosz Bryniarski</h3>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (znajdz.php)
  30. Krok 30: Przycisk „SPRAWDŹ”

    Kryteria:

    R.2.8 Na stronie PHP umieszczono formularz z polem edycyjnym i przyciskiem SPRAWDŹ

    ok. 1 min
    Polecenie z arkusza

    przycisk „SPRAWDŹ”, który wysyła dane

    type="submit" wysyła formularz, value to napis na przycisku - wielkimi literami, jak w arkuszu. Pole i przycisk w formularzu na stronie PHP dają R.2.8. Strona wygląda jeszcze jak zwykły HTML - skrypt dojdzie po stylach.

    znajdz.php PHP zmienione: 1 linia
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <title>Kwiaty</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <header>
            <h1>Moje kwiaty</h1>
        </header>
        <section id="left">
            <h3>Kwiaty dla Ciebie!</h3>
            <a href="https://www.swiatkwiatow.pl/">Rozpoznaj kwiaty</a><br>
            <a href="znajdz.php">Znajdź kwiaciarnię</a><br>
            <img src="gozdzik.jpg" alt="Goździk">
        </section>
        <section id="right">
            <img src="gerbera.jpg" alt="gerbera">
            <img src="gozdzik.jpg" alt="goździk">
            <img src="roza.jpg" alt="róża">
            <p>Podaj miejscowość, w której poszukujesz kwiaciarni:</p>
            <form method="post" action="znajdz.php">
                <input type="text" name="city">
                <input type="submit" value="SPRAWDŹ">
            </form>
        </section>
        <footer>
            <h3>Stronę opracował: Bartosz Bryniarski</h3>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (znajdz.php)
  31. Etap 5: Styl CSS

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

    Krok 31: Plik styl.css: krój, wyśrodkowanie i kursywa

    Kryteria:

    R.4.1 Ustawiono styl domyślny (dla selektora *, lub body, lub html, lub kontenera całej strony) czcionka Times New Roman, wyśrodkowana, kursywa

    ok. 2 min
    Polecenie z arkusza

    Styl CSS zawiera formatowanie: domyślnie dla całej strony: czcionka Times New Roman, tekst wyśrodkowany, kursywa

    Nowy plik styl.css w folderze zdającego. Pierwsza reguła na body - dziedziczą ją wszystkie elementy strony (R.4.1):

    • font-family: "Times New Roman" - nazwa kroju ze spacjami w cudzysłowie,
    • text-align: center - wyśrodkowanie tekstu i elementów liniowych (także obrazów),
    • font-style: italic - kursywa.
    styl.css CSS nowy plik
    body {
        font-family: "Times New Roman";
        text-align: center;
        font-style: italic;
    }
    Podgląd strony po tym kroku (index.html)
  32. Krok 32: Baner: tło, wysokość, margines wewnętrzny górny

    Kryteria:

    R.4.4 Ustawiono margines wewnętrzny górny 10px (padding-top lub padding: 10px 0 0 0) dla banera

    ok. 1 min
    Polecenie z arkusza

    dla banera: kolor tła LightPink, wysokość 80 px, margines wewnętrzny górny 10 px

    Selektor znacznika header. Margines wewnętrzny to padding - padding-top: 10px odsuwa nagłówek od górnej krawędzi banera (R.4.4). Nazwę koloru LightPink wpisujesz dosłownie, przeglądarka ją zna.

    styl.css CSS zmienione: 5 linii
    body {
        font-family: "Times New Roman";
        text-align: center;
        font-style: italic;
    }
    header {
        background-color: LightPink;
        height: 80px;
        padding-top: 10px;
    }
    Podgląd strony po tym kroku (index.html)
  33. Krok 33: Panel lewy: tło, wysokość, szerokość, czcionka

    ok. 1 min
    Polecenie z arkusza

    dla panelu lewego: kolor tła LightPink, wysokość 500 px, szerokość 20%, rozmiar czcionki 20 px

    Selektor identyfikatora #left - z krzyżykiem, bo w HTML-u jest id="left". Szerokość w procentach liczy się od szerokości okna, więc panel zwęża się razem z oknem.

    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 całe połączenie ze stylem za niespełnione.

    styl.css CSS zmienione: 6 linii
    body {
        font-family: "Times New Roman";
        text-align: center;
        font-style: italic;
    }
    header {
        background-color: LightPink;
        height: 80px;
        padding-top: 10px;
    }
    #left {
        background-color: LightPink;
        height: 500px;
        width: 20%;
        font-size: 20px;
    }
    Podgląd strony po tym kroku (index.html)
  34. Krok 34: Panel prawy: czarne tło, różowy tekst

    Kryteria: , ,

    R.4.5 Ustawiono szerokość panelu lewego na 20%, panelu prawego na 80%

    R.4.6 Ustawiono wielkość czcionki dla panelu lewego 20px i prawego 30px

    R.4.7 Ustawiono kolor czcionki LightPink dla panelu prawego

    ok. 1 min
    Polecenie z arkusza

    dla panelu prawego: czarny kolor tła, wysokość 500 px, szerokość 80%, rozmiar czcionki 30 px, kolor czcionki LightPink

    Czarne tło (black) i różowy tekst LightPink (R.4.7). Szerokości 20% + 80% = 100% (R.4.5), rozmiary czcionki 20 px i 30 px w panelach (R.4.6).

    styl.css CSS zmienione: 7 linii
    body {
        font-family: "Times New Roman";
        text-align: center;
        font-style: italic;
    }
    header {
        background-color: LightPink;
        height: 80px;
        padding-top: 10px;
    }
    #left {
        background-color: LightPink;
        height: 500px;
        width: 20%;
        font-size: 20px;
    }
    #right {
        background-color: black;
        height: 500px;
        width: 80%;
        font-size: 30px;
        color: LightPink;
    }
    Podgląd strony po tym kroku (index.html)
  35. Krok 35: Stopka: tło i wysokość

    Kryteria: ,

    R.4.2 Ustawiono kolor tła dla banera, panelu lewego i stopki na LightPink oraz dla panelu prawego na czarny

    R.4.3 Ustawiono wysokość banera 80px, obu paneli 500px, stopki 60px

    ok. 1 min
    Polecenie z arkusza

    dla stopki: kolor tła LightPink, wysokość 60 px

    Kolory tła wszystkich bloków (R.4.2) i wysokości: baner 80 px, panele 500 px, stopka 60 px (R.4.3) są ustawione. Bloki stoją jeszcze jeden pod drugim - układ obok siebie ustawi osobny krok.

    styl.css CSS zmienione: 4 linie
    body {
        font-family: "Times New Roman";
        text-align: center;
        font-style: italic;
    }
    header {
        background-color: LightPink;
        height: 80px;
        padding-top: 10px;
    }
    #left {
        background-color: LightPink;
        height: 500px;
        width: 20%;
        font-size: 20px;
    }
    #right {
        background-color: black;
        height: 500px;
        width: 80%;
        font-size: 30px;
        color: LightPink;
    }
    footer {
        background-color: LightPink;
        height: 60px;
    }
    Podgląd strony po tym kroku (index.html)
  36. Krok 36: Obraz w panelu lewym: 180 × 180 px

    Kryteria:

    R.4.8 Ustawiono styl wyłącznie dla obrazu z panelu lewego: szerokość i wysokość 180px

    ok. 1 min
    Polecenie z arkusza

    wyłącznie dla obrazu z panelu lewego: szerokość i wysokość 180 px

    Selektor potomka #left img - obrazy, które leżą wewnątrz panelu lewego. „Wyłącznie” znaczy, że trzy obrazy panelu prawego mają zostać w swoim rozmiarze 190 px (R.4.8).

    Typowe błędy

    Sam selektor img zmniejszy wszystkie cztery obrazy - kryterium mówi wyraźnie o obrazie z panelu lewego.

    styl.css CSS zmienione: 4 linie
    body {
        font-family: "Times New Roman";
        text-align: center;
        font-style: italic;
    }
    header {
        background-color: LightPink;
        height: 80px;
        padding-top: 10px;
    }
    #left {
        background-color: LightPink;
        height: 500px;
        width: 20%;
        font-size: 20px;
    }
    #right {
        background-color: black;
        height: 500px;
        width: 80%;
        font-size: 30px;
        color: LightPink;
    }
    footer {
        background-color: LightPink;
        height: 60px;
    }
    #left img {
        width: 180px;
        height: 180px;
    }
    Podgląd strony po tym kroku (index.html)
  37. Krok 37: Paragraf: górny margines zewnętrzny 50 px

    Kryteria:

    R.4.9 Ustawiono dla selektora paragrafu: górny margines zewnętrzny 50px

    ok. 1 min
    Polecenie z arkusza

    dla selektora paragrafu: górny margines zewnętrzny 50 px

    Selektor znacznika p, margines zewnętrzny to margin - margin-top: 50px odsuwa paragraf od obrazów nad nim (R.4.9).

    styl.css CSS zmienione: 3 linie
    body {
        font-family: "Times New Roman";
        text-align: center;
        font-style: italic;
    }
    header {
        background-color: LightPink;
        height: 80px;
        padding-top: 10px;
    }
    #left {
        background-color: LightPink;
        height: 500px;
        width: 20%;
        font-size: 20px;
    }
    #right {
        background-color: black;
        height: 500px;
        width: 80%;
        font-size: 30px;
        color: LightPink;
    }
    footer {
        background-color: LightPink;
        height: 60px;
    }
    #left img {
        width: 180px;
        height: 180px;
    }
    p {
        margin-top: 50px;
    }
    Podgląd strony po tym kroku (index.html)
  38. Krok 38: Układ bloków zgodny z obrazem 1

    Kryteria:

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

    ok. 2 min
    Polecenie z arkusza

    Podział strony na bloki: baner, panel lewy i prawy oraz stopkę za pomocą znaczników sekcji

    Obie sekcje dostają float: left - panel lewy (20%) staje przy lewej krawędzi, a prawy (80%) obok niego, bo razem mają dokładnie 100%. Stopka z clear: both zaczyna się dopiero pod oboma panelami. Układ odpowiada obrazowi 1 (R.3.1). Ta sama reguła działa na stronie znajdz.php - obie strony korzystają z jednego pliku stylów.

    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 lewy.

    styl.css CSS zmienione: 6 linii
    body {
        font-family: "Times New Roman";
        text-align: center;
        font-style: italic;
    }
    header {
        background-color: LightPink;
        height: 80px;
        padding-top: 10px;
    }
    #left {
        background-color: LightPink;
        height: 500px;
        width: 20%;
        font-size: 20px;
    }
    #right {
        background-color: black;
        height: 500px;
        width: 80%;
        font-size: 30px;
        color: LightPink;
    }
    footer {
        background-color: LightPink;
        height: 60px;
    }
    #left img {
        width: 180px;
        height: 180px;
    }
    p {
        margin-top: 50px;
    }
    section {
        float: left;
    }
    footer {
        clear: both;
    }
    Podgląd strony po tym kroku (index.html)
  39. Etap 6: Skrypt PHP

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

    Krok 39: Miejsce skryptu i połączenie z bazą kwiaciarnia

    Kryteria: ,

    R.5.1 Skrypt napisano w języku PHP i umieszczono w pliku znajdz.php oraz zawiera on przynajmniej jedną instrukcję języka zgodną ze składnią

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

    ok. 3 min
    Polecenie z arkusza

    Wymagania dotyczące skryptu: Napisany w języku PHP. Skrypt łączy się z serwerem bazy danych na localhost, użytkownik root bez hasła, baza danych o nazwie kwiaciarnia

    Wynik skryptu ma się pojawić pod przyciskiem (obraz 2), więc blok PHP piszesz w pliku znajdz.php zaraz za formularzem, między <?php a ?> (R.5.1). Serwer wykona go, zanim strona trafi do przeglądarki.

    Pierwsza instrukcja: mysqli_connect z tabeli 3 arkusza - kolejno serwer localhost, użytkownik root, puste hasło '' i nazwa bazy kwiaciarnia. Połączenie trafia do zmiennej $connection, z której skorzystają zapytanie i zamknięcie (R.5.2).

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

    znajdz.php PHP zmienione: 3 linie
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <title>Kwiaty</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <header>
            <h1>Moje kwiaty</h1>
        </header>
        <section id="left">
            <h3>Kwiaty dla Ciebie!</h3>
            <a href="https://www.swiatkwiatow.pl/">Rozpoznaj kwiaty</a><br>
            <a href="znajdz.php">Znajdź kwiaciarnię</a><br>
            <img src="gozdzik.jpg" alt="Goździk">
        </section>
        <section id="right">
            <img src="gerbera.jpg" alt="gerbera">
            <img src="gozdzik.jpg" alt="goździk">
            <img src="roza.jpg" alt="róża">
            <p>Podaj miejscowość, w której poszukujesz kwiaciarni:</p>
            <form method="post" action="znajdz.php">
                <input type="text" name="city">
                <input type="submit" value="SPRAWDŹ">
            </form>
    <?php
    $connection = mysqli_connect('localhost', 'root', '', 'kwiaciarnia');
    ?>
        </section>
        <footer>
            <h3>Stronę opracował: Bartosz Bryniarski</h3>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (znajdz.php)
  40. Krok 40: Pobranie miejscowości z pola edycyjnego

    ok. 2 min
    Polecenie z arkusza

    Skrypt pobiera dane z pola edycyjnego

    • isset($_POST['city']) jest prawdziwe dopiero po kliknięciu „SPRAWDŹ”. Przy pierwszym wejściu na stronę formularz nie był wysłany i skrypt niczego nie szuka,
    • $city = $_POST['city']; - wartość pola o name="city" do zmiennej o czytelnej nazwie.

    Podgląd: wysłany formularz z wpisanym „Malbork” - wartość jest już w zmiennej, ale skrypt jeszcze niczego nie wypisuje.

    Typowe błędy

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

    znajdz.php PHP zmienione: 3 linie
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <title>Kwiaty</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <header>
            <h1>Moje kwiaty</h1>
        </header>
        <section id="left">
            <h3>Kwiaty dla Ciebie!</h3>
            <a href="https://www.swiatkwiatow.pl/">Rozpoznaj kwiaty</a><br>
            <a href="znajdz.php">Znajdź kwiaciarnię</a><br>
            <img src="gozdzik.jpg" alt="Goździk">
        </section>
        <section id="right">
            <img src="gerbera.jpg" alt="gerbera">
            <img src="gozdzik.jpg" alt="goździk">
            <img src="roza.jpg" alt="róża">
            <p>Podaj miejscowość, w której poszukujesz kwiaciarni:</p>
            <form method="post" action="znajdz.php">
                <input type="text" name="city">
                <input type="submit" value="SPRAWDŹ">
            </form>
    <?php
    $connection = mysqli_connect('localhost', 'root', '', 'kwiaciarnia');
    if (isset($_POST['city'])) {
        $city = $_POST['city'];
    }
    ?>
        </section>
        <footer>
            <h3>Stronę opracował: Bartosz Bryniarski</h3>
        </footer>
    </body>
    </html>

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

  41. Krok 41: Kwerenda 1 z miejscowością z formularza

    Kryteria:

    R.5.4 Skrypt wysyła do bazy danych zmodyfikowane zapytanie 1 w ten sposób, że w miejscu miasta jest wpisana wartość z pola edycyjnego

    ok. 2 min
    Polecenie z arkusza

    Wysyła do bazy danych zmodyfikowane zapytanie 1 w ten sposób, że w miejscu miasta jest wpisana wartość z pola edycyjnego

    Kwerenda 1 z kwerendy.txt, w której w miejsce 'Malbork' stoi '$city'. Całe zapytanie jest w cudzysłowie "…", więc PHP podstawia wartość zmiennej; apostrofy wewnątrz są ogranicznikami napisu w SQL. mysqli_query wysyła zapytanie i zwraca wynik do $result (R.5.4).

    Podgląd: zapytanie wykonane dla Malborka, ale wynik nie jest jeszcze wypisany.

    Typowe błędy

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

    znajdz.php PHP zmienione: 1 linia
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <title>Kwiaty</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <header>
            <h1>Moje kwiaty</h1>
        </header>
        <section id="left">
            <h3>Kwiaty dla Ciebie!</h3>
            <a href="https://www.swiatkwiatow.pl/">Rozpoznaj kwiaty</a><br>
            <a href="znajdz.php">Znajdź kwiaciarnię</a><br>
            <img src="gozdzik.jpg" alt="Goździk">
        </section>
        <section id="right">
            <img src="gerbera.jpg" alt="gerbera">
            <img src="gozdzik.jpg" alt="goździk">
            <img src="roza.jpg" alt="róża">
            <p>Podaj miejscowość, w której poszukujesz kwiaciarni:</p>
            <form method="post" action="znajdz.php">
                <input type="text" name="city">
                <input type="submit" value="SPRAWDŹ">
            </form>
    <?php
    $connection = mysqli_connect('localhost', 'root', '', 'kwiaciarnia');
    if (isset($_POST['city'])) {
        $city = $_POST['city'];
        $result = mysqli_query($connection, "SELECT nazwa, ulica FROM kwiaciarnie WHERE miasto = '$city';");
    }
    ?>
        </section>
        <footer>
            <h3>Stronę opracował: Bartosz Bryniarski</h3>
        </footer>
    </body>
    </html>

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

  42. Krok 42: Nazwa i ulica pod przyciskiem

    Kryteria:

    R.5.5 Skrypt wyświetla pod przyciskiem zwrócone zapytaniem dane: nazwę i ulicę oddzielone przecinkiem

    ok. 3 min
    Polecenie z arkusza

    Pod przyciskiem wyświetla zwrócone zapytaniem dane: nazwę i ulicę oddzielone przecinkiem

    • mysqli_fetch_row($result) zwraca kolejny wiersz wyniku jako tablicę numerowaną: $row[0] to nazwa, $row[1] to ulica - w kolejności z SELECT. Gdy wierszy zabraknie, zwraca null i pętla while się kończy,
    • echo skleja nazwę, przecinek ze spacją i ulicę operatorem kropki ., a <br> kończy linię - gdyby w mieście było kilka kwiaciarni, każda stanie w osobnym wierszu.

    Podgląd: dla „Malbork” pod przyciskiem stoi Melisa, Konopnickiej - jak na obrazie 2 (R.5.5). Napis nie jest w paragrafie, więc nie dostaje marginesu 50 px i stoi tuż pod formularzem. Dla „Warszawa” skrypt wypisze „Astra, Sobieskiego”, a dla miasta spoza bazy - nic.

    znajdz.php PHP zmienione: 3 linie
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <title>Kwiaty</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <header>
            <h1>Moje kwiaty</h1>
        </header>
        <section id="left">
            <h3>Kwiaty dla Ciebie!</h3>
            <a href="https://www.swiatkwiatow.pl/">Rozpoznaj kwiaty</a><br>
            <a href="znajdz.php">Znajdź kwiaciarnię</a><br>
            <img src="gozdzik.jpg" alt="Goździk">
        </section>
        <section id="right">
            <img src="gerbera.jpg" alt="gerbera">
            <img src="gozdzik.jpg" alt="goździk">
            <img src="roza.jpg" alt="róża">
            <p>Podaj miejscowość, w której poszukujesz kwiaciarni:</p>
            <form method="post" action="znajdz.php">
                <input type="text" name="city">
                <input type="submit" value="SPRAWDŹ">
            </form>
    <?php
    $connection = mysqli_connect('localhost', 'root', '', 'kwiaciarnia');
    if (isset($_POST['city'])) {
        $city = $_POST['city'];
        $result = mysqli_query($connection, "SELECT nazwa, ulica FROM kwiaciarnie WHERE miasto = '$city';");
        while ($row = mysqli_fetch_row($result)) {
            echo $row[0] . ', ' . $row[1] . '<br>';
        }
    }
    ?>
        </section>
        <footer>
            <h3>Stronę opracował: Bartosz Bryniarski</h3>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (znajdz.php)
  43. Krok 43: Zamknięcie połączenia z bazą

    Kryteria:

    R.5.3 Po wykonaniu wszystkich operacji na bazie zastosowano funkcję zamknięcia połączenia z serwerem bazy danych

    ok. 1 min
    Polecenie z arkusza

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

    mysqli_close($connection) na końcu bloku PHP, poza warunkiem - wykona się zawsze, 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 przed pętlą while zamyka połączenie, zanim wynik zostanie odczytany - w PHP 8 kończy się to błędem.

    znajdz.php PHP zmienione: 1 linia
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <title>Kwiaty</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <header>
            <h1>Moje kwiaty</h1>
        </header>
        <section id="left">
            <h3>Kwiaty dla Ciebie!</h3>
            <a href="https://www.swiatkwiatow.pl/">Rozpoznaj kwiaty</a><br>
            <a href="znajdz.php">Znajdź kwiaciarnię</a><br>
            <img src="gozdzik.jpg" alt="Goździk">
        </section>
        <section id="right">
            <img src="gerbera.jpg" alt="gerbera">
            <img src="gozdzik.jpg" alt="goździk">
            <img src="roza.jpg" alt="róża">
            <p>Podaj miejscowość, w której poszukujesz kwiaciarni:</p>
            <form method="post" action="znajdz.php">
                <input type="text" name="city">
                <input type="submit" value="SPRAWDŹ">
            </form>
    <?php
    $connection = mysqli_connect('localhost', 'root', '', 'kwiaciarnia');
    if (isset($_POST['city'])) {
        $city = $_POST['city'];
        $result = mysqli_query($connection, "SELECT nazwa, ulica FROM kwiaciarnie WHERE miasto = '$city';");
        while ($row = mysqli_fetch_row($result)) {
            echo $row[0] . ', ' . $row[1] . '<br>';
        }
    }
    mysqli_close($connection);
    ?>
        </section>
        <footer>
            <h3>Stronę opracował: Bartosz Bryniarski</h3>
        </footer>
    </body>
    </html>

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

  44. Etap 7: Dobre praktyki (poza kluczem)

    Kroki 44-45 · po tym etapie masz 36 z 36 kryteriów (pkt)

    Krok 44: Zabezpieczenie: zapytanie przygotowane

    ok. 4 min
    Polecenie z arkusza

    Wysyła do bazy danych zmodyfikowane zapytanie 1 w ten sposób, że w miejscu miasta jest wpisana wartość z pola edycyjnego

    Wpisana miejscowość trafia do zapytania wprost - to SQL injection. Sprawdzone na wersji z poprzednich kroków:

    • wpis x' OR '1'='1 zamienia warunek w miasto = 'x' OR '1'='1', który jest prawdziwy dla każdego wiersza - skrypt wypisuje obie kwiaciarnie, choć żadna nie jest w mieście „x”. Tak samo da się wyciągnąć dane z innych tabel bazy,
    • miejscowość z apostrofem rozbija składnię zapytania - PHP 8.1 i nowsze zgłaszają wtedy wyjątek mysqli_sql_exception i zamiast strony widać „Fatal error”.

    Lekarstwo to zapytanie przygotowane: mysqli_prepare ze znakiem ? w miejscu miasta, mysqli_stmt_bind_param z typem 's' (napis), mysqli_stmt_execute i mysqli_stmt_get_result, który zwraca zwykły wynik - pętla z mysqli_fetch_row zostaje bez zmian. Baza dostaje treść zapytania i dane osobno, więc dane nigdy nie staną się kodem SQL. Podgląd: ten sam wpis x' OR '1'='1 nie znajduje już niczego. Stara linia zostaje 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.

    znajdz.php PHP zmienione: 5 linii
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <title>Kwiaty</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <header>
            <h1>Moje kwiaty</h1>
        </header>
        <section id="left">
            <h3>Kwiaty dla Ciebie!</h3>
            <a href="https://www.swiatkwiatow.pl/">Rozpoznaj kwiaty</a><br>
            <a href="znajdz.php">Znajdź kwiaciarnię</a><br>
            <img src="gozdzik.jpg" alt="Goździk">
        </section>
        <section id="right">
            <img src="gerbera.jpg" alt="gerbera">
            <img src="gozdzik.jpg" alt="goździk">
            <img src="roza.jpg" alt="róża">
            <p>Podaj miejscowość, w której poszukujesz kwiaciarni:</p>
            <form method="post" action="znajdz.php">
                <input type="text" name="city">
                <input type="submit" value="SPRAWDŹ">
            </form>
    <?php
    $connection = mysqli_connect('localhost', 'root', '', 'kwiaciarnia');
    if (isset($_POST['city'])) {
        $city = $_POST['city'];
        // $result = mysqli_query($connection, "SELECT nazwa, ulica FROM kwiaciarnie WHERE miasto = '$city';");
        $statement = mysqli_prepare($connection, 'SELECT nazwa, ulica FROM kwiaciarnie WHERE miasto = ?;');
        mysqli_stmt_bind_param($statement, 's', $city);
        mysqli_stmt_execute($statement);
        $result = mysqli_stmt_get_result($statement);
        while ($row = mysqli_fetch_row($result)) {
            echo $row[0] . ', ' . $row[1] . '<br>';
        }
    }
    mysqli_close($connection);
    ?>
        </section>
        <footer>
            <h3>Stronę opracował: Bartosz Bryniarski</h3>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (znajdz.php)
  45. Krok 45: Zabezpieczenie: dane z pola i z bazy

    ok. 3 min
    Polecenie z arkusza

    Pod przyciskiem wyświetla zwrócone zapytaniem dane: nazwę i ulicę oddzielone przecinkiem

    Dwie poprawki:

    • trim() zdejmuje spacje z brzegów wpisu - „ Malbork ” ze spacją (częste przy kopiowaniu) w wersji z kluczu nie znajdował niczego, a teraz znajduje Melisę. Pusty wpis albo same spacje w ogóle nie trafiają do bazy (warunek !== ''),
    • htmlspecialchars() przy wypisywaniu - nazwa i ulica pochodzą z bazy, a bazę zapełnia ktoś inny niż skrypt. Gdyby w nazwie kwiaciarni stał znacznik <script>, przeglądarka wykonałaby go u każdego, kto wyszuka to miasto. Funkcja zamienia <, >, & i cudzysłowy na encje, więc znaczniki wyświetlą się jako tekst. To zasada ogólna: wszystko, co wypisujesz z bazy lub z formularza, przechodzi przez htmlspecialchars.

    Podgląd: wpis „ Malbork ” ze spacjami - Melisa, Konopnickiej. Stare linie zostają w komentarzu; na egzaminie wystarczy wersja z kroku „Zamknięcie połączenia”.

    znajdz.php PHP zmienione: 6 linii
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <title>Kwiaty</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <header>
            <h1>Moje kwiaty</h1>
        </header>
        <section id="left">
            <h3>Kwiaty dla Ciebie!</h3>
            <a href="https://www.swiatkwiatow.pl/">Rozpoznaj kwiaty</a><br>
            <a href="znajdz.php">Znajdź kwiaciarnię</a><br>
            <img src="gozdzik.jpg" alt="Goździk">
        </section>
        <section id="right">
            <img src="gerbera.jpg" alt="gerbera">
            <img src="gozdzik.jpg" alt="goździk">
            <img src="roza.jpg" alt="róża">
            <p>Podaj miejscowość, w której poszukujesz kwiaciarni:</p>
            <form method="post" action="znajdz.php">
                <input type="text" name="city">
                <input type="submit" value="SPRAWDŹ">
            </form>
    <?php
    $connection = mysqli_connect('localhost', 'root', '', 'kwiaciarnia');
    // if (isset($_POST['city'])) {
    //     $city = $_POST['city'];
    if (isset($_POST['city']) && trim($_POST['city']) !== '') {
        $city = trim($_POST['city']);
        // $result = mysqli_query($connection, "SELECT nazwa, ulica FROM kwiaciarnie WHERE miasto = '$city';");
        $statement = mysqli_prepare($connection, 'SELECT nazwa, ulica FROM kwiaciarnie WHERE miasto = ?;');
        mysqli_stmt_bind_param($statement, 's', $city);
        mysqli_stmt_execute($statement);
        $result = mysqli_stmt_get_result($statement);
        while ($row = mysqli_fetch_row($result)) {
            // echo $row[0] . ', ' . $row[1] . '<br>';
            echo htmlspecialchars($row[0]) . ', ' . htmlspecialchars($row[1]) . '<br>';
        }
    }
    mysqli_close($connection);
    ?>
        </section>
        <footer>
            <h3>Stronę opracował: Bartosz Bryniarski</h3>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (znajdz.php)
  46. Etap 8: Oddanie pracy

    Krok 46 · po tym etapie masz 36 z 36 kryteriów (pkt)

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

    ok. 5 min
    Polecenie z arkusza

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

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

    W folderze z numerem zdającego muszą być: gerbera.jpg, gozdzik.jpg, index.html, kw1.jpg, kw2.jpg, kw3.jpg, kwerendy.txt, kwiaciarnia.sql, przeglądarka.txt, roza.jpg, styl.css - i znajdz.php, którego arkusz w tej liście nie wymienia, choć to druga strona witryny i jedyny plik ze skryptem (bez niego nie ma punktów R.5). 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 45.

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