Přeskočit obsah
V
Pro vývojáře
Architektura, konvence, jádro systému a bezpečnost
Začínáme / Pětivrstvý model

Pětivrstvý model#

Základ celého systému. Bez jeho pochopení nedává zbytek dokumentace smysl — a hlavně se v kódu nedá vyznat, protože tatáž věc má v každé vrstvě jiné jméno a jinou roli.

Model#

Presenter          tenký; jen volá manager
Manager            veřejné rozhraní domény, lifecycle hooky
Service            tenká vrstva, drží počty, deleguje
Mapper             převádí surová data na entity
Repository         JEDINÉ místo, kde je SQL
Vrstva Smí Nesmí
Presenter volat manager, plnit šablonu dotazovat se do databáze, obsahovat doménovou logiku
Manager doménová logika, hooky, orchestrace; injektovat jiné managery psát SQL
Service delegovat, držet totalCount doménová rozhodnutí, injektovat jiné service
Mapper hydratovat data na entity psát SQL
Repository SQL a QueryBuilder doménová logika

Zkratka přes vrstvu se vždycky vrátí

Dotaz z presenteru přímo do repository funguje — dokud někdo nepotřebuje totéž volat z jiné sekce. Pak se logika duplikuje a jedna z kopií se přestane opravovat.

Manager je JEDINÁ vrstva, která smí injektovat jiné managery

Service, Mapper i Repository jsou uzavřené: service drží jen svůj mapper, mapper jen svou repository. XxxRunner nebo XxxResolver v Models/Services/, který si injektuje manager, je porušení — patří do manager-tier vedle entitního manageru.

Front nesahá do databáze#

Nejdůležitější důsledek modelu. Front ani administrace nemají k databázi přístup. Data si vyžádají od Api sekce přes most (app/Core/Bridge/ApiBridge.php).

Front Manager → Service → Mapper → Repository → ApiBridge
                          interní volání (bez HTTP) nebo HTTP požadavek
                                            Api presenter

Tentýž modul má víc sad entit

App\UI\Front\Eshop\Models\Entities\Product a App\UI\Api\Eshop\Models\Entities\Product jsou dvě různé třídy. Api entita je Doctrine entita nad tabulkou, Front entita je výsledek hydratace odpovědi. Záměna těch dvou je nejčastější chyba nováčka v tomhle systému — a projeví se jako „TypeError někde úplně jinde“.

Mezi sekcemi teče POLE, ne objekt

Přes most jde array. Objekt na druhé straně teprve vzniká hydratací — proto jsou v systému dva hydrátory, každý pro jednu stranu.

Front manager umí jen číst#

Základní front manager má jen čtecí traityGetTrait, GetByTrait, GetAllTrait, TotalCountTrait. Zápis si musí manager vyžádat explicitně:

use App\Core\Traits\Shared\Models\Managers\DeleteTrait;
use App\Core\Traits\Shared\Models\Managers\SaveTrait;

class AdvertFollowerManager extends BaseManager
{
    use SaveTrait;
    use DeleteTrait;
}

Dělá to 25 ze 111 frontových managerů. Admin a Api základ má zápis rovnou v sobě.

Je to záměrná brzda, ne opomenutí

Zápis z veřejného webu je výjimka, která má být vidět v kódu — ne něco, co se „prostě dá“.

Bázové třídy#

Každá vrstva má předka v app/Core/Base/, a to zvlášť pro každou sekci:

app/Core/Base/
  Api/     Front/     Admin/     Cron/     Script/     Shared/
    Models/Managers/Manager.php
    Models/Services/…
    Models/Mappers/…
    Models/Repositories/…

Sdílené implementace jsou v app/Core/Traits/<Sekce>/Models/.

Mapper má dvě podoby#

Kde Složka Co dělá
Api modul Mappers/Db/ mapuje nad databází
Front/Admin modul Mappers/Api/ hydratuje odpověď z API

Je to tatáž vrstva ve dvou různých rolích — proto se jmenuje stejně.

Postup: přidávám čtení nové entity#

  1. Api strana: entita → repository (SQL) → mapper → service → manager → get*Data() v presenteru s guardem oprávnění.
  2. Klíč oprávnění do databáze ve tvaru :Api:<Modul>:<Entita>:<akce>.
  3. Front/Admin strana: varianta entity s hydratačními atributy → repository s apiEndpoint → mapper → service → manager.
  4. Presenter injektuje jen manager a volá findAll(…)->execute().
  5. Ověř obě cesty — přes stránku i přímo přes most.

Podrobně Volání API a Konvence kódu.

Proč to tak je#

Admin, Front i cron jdou stejnou Api cestou. Doménová logika v manageru tedy platí pro všechny vstupy naráz — nemusí se psát třikrát a nemůže se rozejít.

Vedlejší efekt: API je hotové jako první

Protože Front sám používá Api, je API pro třetí strany funkční od začátku, ne až jako dodatek. Viz manuál pro API.

Cena je jedno hrdlo navíc

Každé čtení jde přes get*Data(), tedy i přes autorizační guard a přes clearDoctrine(). To druhé je nejzávažnější landmina systému.

Navazující kapitoly: Struktura projektu · Volání API · Hydrátory · Identity mapa · Konvence kódu