ID kontrolery

Že každý záznam v databázové tabulce je nutné nějak jednoznačně identifikovat určitě není třeba říkat. A jistě, dá se říct, že v našem oboru je tradiční autoincrement id - je to taková klasika. Ale rozhodně to není jediný způsob jak záznamy identifikovat.

Opět si jako příklad vezmeme články z ukázkové aplikace. Konkrétně entitu articles_localized, třídu JetApplication\Content_Article_Localized. Když se kouknete na její definici, tak zjistíte, že žádné klasické autoincrement id tam není. Identifikaci tvoří tyto dvě vlastnosti: namespace JetApplication;

use 
Jet\DataModel;
use 
Jet\DataModel_Definition;
use 
Jet\DataModel_Related_1toN;
use 
Jet\DataModel_IDController_Passive;

use 
Jet\Form_Definition;


#[
DataModel_Definition(
    
name'article_localized',
    
database_table_name'articles_localized',
    
id_controller_classDataModel_IDController_Passive::class,
    
parent_model_classContent_Article::class
)]
class 
Content_Article_Localized extends DataModel_Related_1toN
{

    #[
DataModel_Definition(
        
typeDataModel::TYPE_ID,
        
is_idtrue,
        
related_to'main.id',
        
do_not_exporttrue
    
)]
    protected 
string|null $article_id '';

    #[
DataModel_Definition(
        
typeDataModel::TYPE_LOCALE,
        
is_idtrue,
        
do_not_exporttrue
    
)]
    protected 
Locale|null $locale;

}

Tedy identifikaci záznamu tvoří ID článku ke kterému náleží jeho lokalizovaná verze a jako identifikace je rovněž označena lokalizace dané mutace článku. U obou vlastností je atribut is_id: true. Vlastnost $article_id je pak navázána na vlastnost $id hlavní entity (atribut related_to: 'main.id' ) a jedná se textový řetězec (o tom si něco povíme později).

A pokud kouknete do vaší databáze na strukturu tabulky articles_localized, tak uvidíte, že má primární klíč nad sloupci, které reprezentují tyto dvě vlastnosti. Tedy kombinace těchto dvou údajů je jednoznačná identifikace záznamu.

Již jsem zmínil, že ID článku (tedy vlastnosti $id entity article ve třídě JetApplication\Content_Article) není typu DataModel::TYPE_ID_AUTOINCREMENT, ale typu DataModel::TYPE_ID, což reprezentuje nějaký textový identifikátor. To jest opět odchylka od nejtradičnějšího způsobu práce s pomocí autoincrement id.

Koukněme se na definici antiti article, třídu JetApplication\Content_Article:

namespace JetApplication;

use 
Jet\DataModel;
use 
Jet\DataModel_Definition;
use 
Jet\DataModel_IDController_UniqueString;

#[
DataModel_Definition(
    
name'article',
    
database_table_name'articles',
    
id_controller_classDataModel_IDController_UniqueString::class,
    
id_controller_options: [
        
'id_property_name' => 'id'
    
]
)]
class 
Content_Article extends DataModel
{
    #[
DataModel_Definition(
        
typeDataModel::TYPE_ID,
        
is_idtrue
    
)]
    protected 
string $id '';
    
}

Proč to tak je? Někdy se může stát, že potřebujete záznamy přenášet mezi několika systémy, nebo několika instancemi systémů, kde každý má svou databázi. Například u článků je to pravděpodobné. A číselné ID (ač je to fakt super věc!) může v takové situaci kolidovat. Tedy v situacích kdy potřebujeme unikátnost (s velkou pravděpodobností) ID v rámci několika oddělených systémů je vhodné použít právě identifikaci pomocí náhodných řetězců.

Pojďme na chvíli pryč od příkladu s článkem a vraťme se k naší staré známé klasice ... Autoincrement id, které je použito (opět sáhnu do ukázkové aplikace pro reálný příklad) například pro uživatelské účty, dejme tomu pro administrátora: namespace JetApplication;

use 
Jet\Auth_User_Interface;
use 
Jet\DataModel;
use 
Jet\DataModel_Definition;
use 
Jet\DataModel_IDController_AutoIncrement;

#[
DataModel_Definition(
    
name'user',
    
database_table_name'users_administrators',
    
id_controller_classDataModel_IDController_AutoIncrement::class,
    
id_controller_options: ['id_property_name' => 'id']
)]
class 
Auth_Administrator_User extends DataModel implements Auth_User_Interface
{

    
/**
     * @var int
     */
    
#[DataModel_Definition(
        
typeDataModel::TYPE_ID_AUTOINCREMENT,
        
is_idtrue
    
)]
    protected 
int $id 0;

    
//... ... ...
}

Tak tedy máme různé situace a ORM DataModel si s tím musí nějak poradit. A aby toho nebylo málo, tak je reálně možné, že vy budete potřebovat pro vaše aplikace ještě úplně jiný způsob identifikace záznamů. Tedy to jak se s ID záznamu operuje nesmí být pevně dáno a musí to být flexibilní systém.

A právě proto má Jet DataModel systém ID kontrolerů. ID kontroler je třída, která implementuje logiku pomocí která bude aplikována a práci s ID záznamů. Několik tříd má Jet DataModel již připraveno, ale vůbec nic vám nebrání vytvořit si vlastní ID kontroler.

Jak již víte z kapitoly o definicích, tak to jaký ID kontroler entita (třída) používá je nutné definovat. Když se vrátíme hned k prvnímu příkladu a to třídě JetApplication\Content_Article_Localized, tak si můžete všimnout této definice:

//... ... ...
#[DataModel_Definition(
    
//... ... ...
    
id_controller_classDataModel_IDController_Passive::class,
    
//... ... ...
)]
class 
Content_Article_Localized extends DataModel_Related_1toN {
    
//... ... ...
}

Třída JetApplication\Content_Article má tuto definici:

//... ... ...
#[DataModel_Definition(
    
//... ... ...
    
id_controller_classDataModel_IDController_UniqueString::class,
    
id_controller_options: [
        
'id_property_name' => 'id'
    
]
)]
class 
Content_Article extends DataModel
{
    
//... ... ...
}

A třída JetApplication\Auth_Administrator_User tuto:

//... ... ... 
#[DataModel_Definition(
    
//... ... ... 
    
id_controller_classDataModel_IDController_AutoIncrement::class,
    
id_controller_options: ['id_property_name' => 'id']
)]
class 
Auth_Administrator_User extends DataModel implements Auth_User_Interface
{
    
//... ... ... 
}

Tedy vidíte, že stačí pouze určovat třídu pomocí atributu id_controller_class a případně parametry kontroleru pomocí id_controller_options. Právě použitá třída ID kontroleru určuje celé chování logiky identifikace záznamu.

Co ID kontroler dělá?

Již bylo řečeno, že ID kontroler se stará o implementaci logiky práce s identifikací záznamu. Ale to je dost široký pojem, tak si řekněme co konkrétně to znamená:

  • Operace při vytváření záznamu (ukládání nového záznamu)
    Například pokud je identrifikátor klasické autoincrement id, pak je nutné po uložení záznamu získat od backendu hodnotu vygenerovanou databází a tuto hodnotu přidělit příslušné vlastnosti třídy. Nebo pokud se jedná o náhodný textový řetězec, tak je nutné jej vygenerovat a hodnotu předat vlastnosti ještě před uložením nového záznamu.
  • Nosič identifikace záznamu
    Jak jsme si ukázali na příkladu jazykové mutace článku, tak záznam nemusí být nutné identifikován jednou vlastností, ale dvěma i více vlastnostmi. Ovšem pro interní účely DataModel je nutné přenášet identifikaci unifikovaně. Ať je identifikace jakéhokoliv typu a ať je tvořena libovolným počtem vlastností, tak musí existovat jednotný způsob přenášení této identifikace. A tímto nosičem je právě konkrétní instance ID kontroleru vázaná na konkrétní instanci entity (konkrétního článku, konkrétního uživatele a tak dále).
  • Provázanost vnitřních relací
    Opět si půjčme článek jako ukázkový příklad. Ukládáte nový článek co má N lokalizací. Lokalizace článku jsou již vytvořené, dokonce naplněné textem, je jasný kód lokalizace. Ale v momentě zakládání nového článku vůbec není známo jeho ID. To se vygeneruje při ukládání (buď před uložením, nebo po uložení - dle typu ID kontroleru). A něco se musí postarat o to, aby subentity znaly před svým uložením ID hlavní entity. Tedy něco musí po uložení hlavního záznamu článku nastavit lokalizacím i to jaký má nový článek ID. A i to dělá Jet DataModel automaticky s dopomocí systému ID kontrolerů.

Předpřipravené ID kontrolery

ID kontroler Význam
Jet\DataModel_IDController_AutoIncrement Klasický přístup, který předpokládá číselnou sekvenci vygenerovanou databází po uložení záznamu.
Jet\DataModel_IDController_UniqueString Před uložením nového záznamu generuje náhodní řetězec s časovým razítkem na začátku.
Jet\DataModel_IDController_Passive Zcela pasivní kontroler. Předpokládá, že potřebné hodnoty pro ID nastaví logika aplikace a/nebo vnitřní relace.

Vlastní ID kontroler

Vůbec nic vám nebrání vytvořit si vlastní ID kontroler pokud vám nestačí ty předdefinované. Ba naopak se to očekává. Jedinou podmínkou je, aby dědil od třídy Jet\DataModel_IDController.

Předchozí kapitola
Definice
Další kapitola
Vnitřní relace