Jdi na navigaci předmětu

Zadání na cvičení

Počínaje tímto cvičením budeme vytvářet aplikaci – primitivní eshop. Cílem tohoto cvičení je vytvořit datový model eshopové aplikace. Stránka má dvě části:

  • Část A je vytvořena společnými silami v rámci výkladové části cvičení.
  • Část B je určena pro samostatné zpracování a je možné za ni získat až 1 bod za aktivitu na cvičení.

Hotové řešení části A je k dispozici v repozitáři Tutorials.

Pravidla pro psaní kódu

Je důležité respektovat pravidla pro psaní kódu. Jinak nevznikne kód, který půjde dlouhodobě udržovat. V rámci cvičení respektujte alespoň následující:

  • Jména tříd se zapisují camel-case a s prvním velkým písmenem (např. ClassName).
  • Každá třída je uložena v samostatném souboru. Název souboru je tvořen názvem třídy a příponou .php (např. ClassName.php).
  • Jména konstant jsou psána velkými písmeny, podtržítko odděluje slova (např. MY_CONSTANT).
  • Názvy metod jsou psány camel-case a začínají malým písmenem (např. myMethod()).
  • Pro jména vlastností je vhodné zvolit konvenci, která bude ve vašem kódu jednotně dodržována (např. $myProperty, $my_property).

Struktura projektu

Všechny třídy modelu patří do jmenného prostoru Eshop\Model. Adresářová struktura respektuje standard PSR-4, tj. prefix Eshop\ odpovídá složce src/:

eshop/
├── index.php              # spouštěcí skript
└── src/
    └── Model/
        ├── HasId.php      # trait; Eshop\Model\HasId
        ├── Product.php    # Eshop\Model\Product
        └── ...

Část A: společně na cvičení

Třída Product

Vytvořte třídu Product s následujícími atributy:

  • id (int) – bude vygenerována pomocí traitu HasId (viz níže)
  • name (string)
  • price (float) – cena bez DPH
  • vatRate (int, procento z rozsahu 0 až 100)

Atributy deklarujte přímo v konstruktoru (constructor property promotion). Gettery a settery nechte vygenerovat IDE. Dále implementujte metodu getPriceVat(), která spočítá cenu včetně daně.

Trait pro generování ID

Každá modelová třída potřebuje unikátní identifikátor. Vytvořte trait HasId, který obsahuje:

  • atribut id (int),
  • statický čítač, ze kterého se ID přidělují,
  • metodu getId(),
  • pomocnou metodu, která ID přidělí (volá se z konstruktoru třídy).

Ověření

V souboru index.php načtěte oba soubory pomocí require, vytvořte několik produktů a vypište je pomocí print_r():

<?php
require 'src/Model/HasId.php';
require 'src/Model/Product.php';

use Eshop\Model\Product;

$products = [
  new Product('Mitsubishi Lancer', 320000, 21),
  new Product('Škoda Octavia', 960000, 21),
];
print_r($products);

Všimněte si, že s každou další třídou přibude další řádek require. Tento problém řeší autoloading, viz část B.

Část B: samostatně, za bod

Navažte na kód z části A. Body za jednotlivé sekce jsou nezávislé – lze získat i část bodu.

Zákazníci (0.5 B)

Vytvořte následující třídy:

  • Customer: abstraktní třída se společnými atributy
    • id (int) – pomocí traitu HasId
    • name (string)
  • UnregisteredCustomer: potomek Customer; nemá žádné další atributy
  • RegisteredCustomer: potomek Customer; navíc má atributy:
    • loyaltyPoints (int)

Dále:

  1. Vytvořte konstantu RegisteredCustomer::REGISTRATION_LOYALTY_POINTS s počátečním počtem věrnostních bodů (hodnotu zvolte).
  2. Implementujte metodu UnregisteredCustomer::register(): RegisteredCustomer, pomocí které se může neregistrovaný zákazník stát registrovaným. Jméno se přenese z původní instance, věrnostní body se nastaví na hodnotu konstanty. Nová instance dostane nové ID.

Objednávka (0.5 B)

Vytvořte třídu Order s atributy:

  • id (int) – pomocí traitu HasId
  • created (DateTimeImmutable) – datum vytvoření, nastaví se v konstruktoru
  • ordered (?DateTimeImmutable) – datum dokončení; null, dokud objednávka není dokončena
  • customer (Customer)
  • items (Product[])

Pro atributy typu pole místo setteru poskytněte metody addItem(Product $item) a removeItem(Product $item).

Dále:

  1. Vytvořte metodu getTotalPriceVat(): float, která vrátí celkovou cenu objednávky včetně daně.
  2. Vytvořte konstantu RegisteredCustomer::LOYALTY_POINTS_COEF (koeficient pro výpočet věrnostních bodů; hodnotu zvolte).
  3. Vytvořte metodu Order::doOrder(), která dokončí objednávku, tj.:
    • nastaví datum dokončení objednávky (ordered) a
    • pokud je zákazník registrovaný, zvýší mu počet věrnostních bodů podle vzorce celková cena objednávky vč. daně * koeficient.

Autoloading (0.5 B)

  • Napište a zaregistrujte funkci, která zajišťuje autoloading potřebných souborů. Předpokládejte, že zdrojové soubory jsou umístěny v adresáři src a jejich další umístění respektuje standard PSR-4.
  • Odstraňte z index.php všechny řádky require odkazující na soubory modelu.

Testy (0.5 B)

Tato část slouží k dokázání, že zpracované řešení skutečně funguje (v budoucnu může být nahrazeno opravdovými testy). Rozšiřte soubor index.php z části A tak, aby:

  • vytvořil několik instancí reprezentující produkty,
  • vytvořil několik instancí reprezentující zákazníky (registrované i neregistrované),
  • vytvořil několik objednávek zákazníků, alespoň jednu dokončil a
  • struktury vypsal pomocí příkazu print_r(), příp. var_dump().