Jednoduché API pro správu zaměstnanců.
Nejjednodušeji s využitím připravených Make příkazů.
make installspustí klasickýcomposer install.make initzkopírujeconfig/local.neon.exampledoconfig/local.neonmake setupvytvoří složkyvar/tmpavar/loga nastaví jim práva pro zápismake fixtureszkopíruje datové xml souboryuser.xmlaemployee.xmlze složkydata/xml/fixturesdodata/xml.
Příkazem make dev, který spustí PHP server na adrese http://localhost:8000/ .
Ukázkový endpoint pro seznam zaměstnanců je dostupný na adrese http://localhost:8000/api/v1/employees/?_access_token=admin (GET request).
Kompletní seznam endpointů pak najdete:
- buď v OpenAPI JSON formátu na adrese http://localhost:8000/api/public/v1/openapi/meta
- nebo v Postman kolekci https://api.postman.com/collections/24797339-86494b6e-0341-426a-b5e8-f636e1b926a1?access_key=PMAT-01HPFJ3590ZN0CXY2FEXHX8E65
- (nejsnadněji lze v desktopové aplikaci Postmana importovat kolekci přes její URL a následně volat jednotlivé requesty).
Nástroje pro zajištění kvality kódu jsou dostupné prostřednictvím následujících Make příkazů:
make tests- unit, integrační a end-to-end testymake phpstan- PhpStanmake cs- code sniffer,make csf- code sniffer s automatickou opravou chyb
Jako kostru aplikace jsem zvolila Apitte skeleton, který je základem API nad Nette a zahrnuje všechny
základní funkce včetně jednoduché autentizace. Protože jsem pro vývoj zvolila nejnovější PHP 8.3,
bylo třeba před vlastním vývojem několik drobných úprav jak ve skeletonu, tak v knihovně Faker použité pro generování fixtures
(cílem bylo zprovoznit QA nástroje a ověřit si, že je projekt funkční).
Následně jsem implementovala EntityManager a XmlDriver s využitím tříd DOMDocument a DOMXPath a použila je namísto Doctrine ORM,
které je součástí skeletonu, ale je vhodné pouze pro práci s relačními databázemi.
Při implementaci EntityManageru jsem využila návrhový vzor IdentityMap pro snadnou práci s entitami
a zamezení vzniku duplicitních instancí entit téhož XML záznamu.
Pro typovou konverzi dat mezi XML souborem a PHP entitou jsem implementovala statickou třídu TypeConverter,
která pokrývá datové typy použité v XML a v PHP entitách a definuje možnosti konverzí mezi nimi.
XML soubor s daty uživatelů jsem vytvořila exportem z původní databázové tabulky uživatelů ze skeletonu.
Následně jsem pouze upravila formát datetime a nullable elementů pro kompatibilitu s XML.
Pro validaci jsem použila Symfony\Validator ze skeletonu, který jsem rozšířila o vlastní typ Gender (pohlaví zaměstnance).
ID v XML záznamech jsou integerová, o autoinkrementaci ID při vytvoření nového záznamu se stará EntityManager.
Při vývoji EntityMangeru jsem se rámcově inspirovala prací s entitami v Doctrine (především pokud jde o funkčnost IdentityMap
a princip persistence entit).
Pro samotnou práci s XML, získávání, ukládání a konverze dat slouží třída XmlDriver. Ke každému XML souboru se
při práci s daty generuje XSD schéma, které XmlDriver automaticky přegeneruje při každé změně ve třídě příslušné entity,
což ulehčuje přidávání nových atributů.
V rámci aplikace je XmlDriver a EntityManager zapouzdřený v repozitáři (AbstractRepository), který nabízí klasické metody pro získávání,
vytváření, updatování a mazání entit. Každá entita (User, Employee) má vlastní repozitář (UserRepository, EmployeeRepository).
Ze strany API endpointů se v aplikaci pracuje s controllery (např. EmployeesControler) a s fasádami (např. EmployeeFacade),
ze kterých se volají metody repozitářů.
Aplikace má potenciál pro zlepšení ve směru přidání testů nebo větší konfigurovatelnosti, což jsem z časových důvodů nerealizovala.
- Přidat property v
App\Domain\Employeeentitě. Property musí mít atributProperty, který definuje datový typ v XML, zda je hodnota nullable a zda má být unikátní v rámci XML souboru. Toto je jediný nutný krok, ostatní kroky jsou volitené podle potřeby. - Pokud má být property nastavitelná přes API, je třeba ji přidat také do kostruktoru entity
(volaného při vytváření entity přes API v metodě
EmployeeFacade::create) a/nebo na ni napsat setter (a přidat jeho volání do metodyEmployeeFacade::update). - Pokud property nemá defaultní hodnotu a není
nullable, je třeba ručně doplnit XML elementy k existujícím entitám v XML souboru. XSD schéma není třeba upravovat, přegeneruje se automaticky. - Kromě toho je třeba přidat property do
RequestaResponseDTO objektů k dané entitě:CreateEmployeeRequestDtopro nastavení hodnoty při vytváření zaměstnanceUpdateEmployeeRequestDtopro nastavení při updatu zaměstnance- Pokud má property specifický typ, je třeba na něj napsat validátor a validační constraint po vzoru
App\Validator\Constraint\GenderValidatoraApp\Validator\Constraint\Gendera přidat konverzi v obou směrech (z PHP do XML a zpět) do třídyApp\Model\Database\TypeConvertera typ přidat do enumuApp\Model\Database\PhpType. EmployeeResponseDto, pokud má být nová property vracena v rámci dat zaměstnance dostupných přes GET endpointy