Definice

Jak jste si určitě všimli v úvodních příkladech, tak Jet\Configu využívá atributy (PHP 8) pro které má Jet svou malou nadstavbu Jet\Attributes.

Patřičné atributy musí mít jak třída, která definici konfigurace reprezentuje, tak její vlastnosti, které reprezentují již jednotlivé konfigurační hodnoty.

(Třída pochopitelně může mít pro své interní účely i další vlastnosti zcela bez definic)

Přehled atributů definic si ukážeme dále.

Definice třídy

Definice třídy má aktuálně jediný parametr a tím je název konfigurace - parametr name. Pomocí tohoto parametru se určuje název definované konfigurace a slouží zejména pro ukládání.

Tedy každá třída reprezentující konfiguraci musí určovat název oné konfigurace a musí začínat například takto: namespace Jet;

#[
Config_Definition(name'db')]
class 
Db_Config extends Config
{
    
//... ... ...
}

Definice vlastnosti - konfigurační hodnoty

Zde už je situace o dost zajímavější :-)

Ty vlastnosti třídy které mají konfigurační definici jsou brány jako konfigurační hodnoty. Platí, že název vlastnosti třídy = název konfigurační hodnoty a pod stejným názvem (nebo v tomto kontextu lépe řečeno klíčem) bude hodnota ukládána do konfiguračního souboru.

Ovšem aby byla definice k něčemu opravdu užitečná, tak je třeba znát mnohem víc informací než je název konfigurační hodnoty / kliče.

Ukažme si opět reálný příklad definice vlastnosti / konfigurační hodnoty, který je přímo z knihovny Jet: namespace Jet;

#[
Config_Definition(name'db')]
class 
Db_Config extends Config
{
    #[
Config_Definition(
        
typeConfig::TYPE_STRING,
        
is_requiredtrue,
    )]
    #[
Form_Definition(
        
typeForm::TYPE_SELECT,
        
is_requiredtrue,
        
label'Default connection:',
        
help_text'Connection name - default value for Db::get()',
        
select_options_creator: [
            
Db_Config::class,
            
'getConnectionsList'
        
],
        
error_messages: [
            
Form_Field::ERROR_CODE_EMPTY => 'Please select default connection',
            
Form_Field::ERROR_CODE_INVALID_VALUE => 'Please select default connection'
        
]
    )]
    protected 
string $default_connection_name 'default';

    public function 
getDefaultConnectionName(): string
    
{
        return 
$this->default_connection_name;
    }

    public function 
setDefaultConnectionNamestring $default_connection_name ): void
    
{
        
$this->default_connection_name $default_connection_name;
    }

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

Jak vidíte, tak vlastnost má getter a setter (což je dobrý zvyk, který vřele doporučuji - na velkých a dlouhodobých projektech se to vždy vyplatí) a především více atributů. Pojďme se na ně kouknout.

Základní atributy

Atribut Význam
type Typ hodnoty. Typ může být:
  • Config::TYPE_STRING
    Textová hodnota. Má další specifické atributy - viz dále.
  • Config::TYPE_BOOL
    Bool hodnota.
  • Config::TYPE_INT
    Celé číslo. Má další specifické atributy - viz dále.
  • Config::TYPE_FLOAT
    Desetinné číslo. Má další specifické atributy - viz dále.
  • Config::TYPE_ARRAY
    Prosté pole libovolných hodnot.
  • Config::TYPE_SECTION
    Podsekce konfigurace - viz dále.
  • Config::TYPE_SECTIONS
    Několik podsekcí konfigurace - například několik databázových spojení a podobně. Viz dále.
is_required Indikuje zda je definice dané hodnoty povinná. Tedy zda v konfiguraci musí být daná hodnota / klíč.

Specifické atributy

Dále si ukážeme atributy vázané na určité typy konfiguračních hodnot.

Config::TYPE_STRING

Atribut Význam
validation_regexp Textová hodnota může být případně validována pomocí regulárního výrazu pomocí kterého je konfigurační hodnota kontrolována.

Config::TYPE_INT a Config::TYPE_FLOAT

Atribut Význam
min_value Číselná hodnota může mít definovanou a ověřovanou minimální hodnotu
max_value Číselná hodnota může mít definovanou a ověřovanou maximální hodnotu

Config::TYPE_SECTION a Config::TYPE_SECTIONS

Atribut Význam
section_creator_method_name Název tovární metody pro vytváření definic podsekcí konfigurace. Ovšem toto je samostatné tém - viz dále

Atributy Form_Definition(*)

Jistě jste si v příkladech všimli atributů Form_Definition. Toto přímo nesouvisí s konfigurací. V Jet můžete takto definovat formulář vlastně na jakékoliv třídě díky mapování tříd na formuláře. Je to univerzální systém, se kterým konfigurace automaticky počítá, ale který je obecně použitelný.

Podsekce konfigurace

O toto téma jsme již lehce zavadili v souvislosti s typy Config::TYPE_SECTION a Config::TYPE_SECTIONS. Nyní si to vysvětlíme podrobněji.

Konfigurace zdaleka není pouze jednoduchá struktura typu klíč -> hodnota. Často potřebujeme podsekce, seznamy podsekcí a to ať už důvodu přehlednosti, tak zejména z důvodů praktických. Ukažme si to opět rovnou na reálném příkladu.

Tím typickým příkladem přímo z "vnitřností" Jet může být konfigurace připojení k databázi Jet\Db.

Tentokrát si pro názornost neukážeme hned třídy, ale příklad již uložené konfigurace: return [
    
'default_connection_name' => 'default',
    
'connections' => [
        
'default' => [
            
'driver' => 'mysql',
            
'name' => 'default',
            
'host' => 'localhost',
            
'port' => 3306,
            
'dbname' => 'our_db',
            
'charset' => 'utf8',
            
'username' => '*******',
            
'password' => '*******',
        ],
        
'erp' => [
            
'driver' => 'oci',
            
'dsn' => 'dbname=//111.222.111.222:1521/erp_db',
            
'username' => '*******',
            
'password' => '*******',
        ],
        
'some_small_db' => [
            
'driver' => 'sqlite',
            
'name' => 'default',
            
'path' => '/*****************************/application/data/db.sq3',
        ],

    ],
];

Jak je zřejmé, tak spojení na relační databáze může existovat víc než jedno.

A také je patrné, že každé spojení má přesně danou sadu konfiguračních hodnot, která musí být definována, ale zároveň každý typ spojení může mít jinou podobu dle typu databáze.

Jak toho docílit si ukážeme za chvíli. Nejprve se vraťme je třídě Jet\Db_Config, jejíž část jsme si ukazovali v této kapitole.

Předchozí ukázka konfigurační třídy Jet\Db_Config byla pouze o parametru / klíči 'default_connection_name'.

Nyní si ukažme tu část, která řeší 'connections': #[Config_Definition(name'db')]
class 
Db_Config extends Config
{
    #[
Config_Definition(
        
typeConfig::TYPE_SECTIONS,
        
section_creator_method_name'connectionConfigCreator'
    
)]
    protected ?array 
$connections null;

    public function 
connectionConfigCreator( array $data ): Db_Backend_Config
    
{
        return 
Factory_Db::getBackendConfigInstance$data );
    }

    
/**
     * @return Db_Backend_Config[]
     */
    
public function getConnections(): array
    {
        return 
$this->connections;
    }

    public function 
getConnectionstring $connection_name ): Db_Backend_Config|null
    
{
        if( !isset( 
$this->connections[$connection_name] ) ) {
            return 
null;
        }

        return 
$this->connections[$connection_name];
    }

    public function 
addConnectionstring $connection_nameDb_Backend_Config $connection_configuration ): void
    
{
        
$this->connections[$connection_name] = $connection_configuration;
    }
    
    public function 
deleteConnectionstring $connection_name ): void
    
{
        if( isset( 
$this->connections[$connection_name] ) ) {
            unset( 
$this->connections[$connection_name] );
        }
    }
}

Jak vidíte, tak třída má vlastnost $connections a ta je definována jako typ Config::TYPE_SECTIONS.

Zároveň je pomocí atributu section_creator_method_name definován název tovární metody. Tovární metoda se stará o to, aby se ze surových dat v podobě načteného asociovaného pole stala definice spojení - tedy instance určité příslušné třídy, která představuje definici konkrétní části konfigurace (zde konkrétního spojení).

Definici části konfigurace v tomto případě představuje třída Jet\Db_Backend_Config (respektive ve skutečnosti o třídu Jet\Db_Backend_PDO_Config, ale teď to nekomplikujme :-) ).

Určitě vaší pozornosti neušlo použití továrny ( Factory_Db::getBackendConfigInstance( $data )) - tedy třída je zaměnitelná, ale to nesouvisí s tématem konfigurace a její definice. Zpět k tématu :-)

Shrňme si to - pokud budete chtít mít v konfiguraci podsekci, nebo podsekce, tak potřebujete:

  • V definici konfigurace mýt vlastnost (vlastnosti) typu Config::TYPE_SECTION (pokud má jít o prostou podsekci), nebo Config::TYPE_SECTIONS (pokud má jít o seznam jako v tomto případě).
  • Potřebujete mít definiční třídu pro danou sekci / sekce. V tomto případě tedy Db_Backend_Config, která již definuje konfiguraci konkrétního připojení na databázi.
  • V hlavní třídě definující konfiguraci je určit vhodné mít další metody pro manipulaci se sekcemi. Jako například v tomto příkladu pro přidávání a odebírání spojení a tak dále.

Definice sekce konfigurace pak může mít například tuto podobu: #[Config_Definition]
abstract class 
Db_Backend_Config extends Config_Section
{
    #[
Config_Definition(
        
typeConfig::TYPE_STRING,
        
is_requiredtrue,
    )]
    #[
Form_Definition(
        
typeForm::TYPE_SELECT,
        
label'Driver',
        
help_text'PDO driver',
        
is_requiredtrue,
        
select_options_creator: [
            
self::class,
            
'getDrivers'
        
],
        
error_messages: [
            
Form_Field::ERROR_CODE_EMPTY => 'Please select driver',
            
Form_Field::ERROR_CODE_INVALID_VALUE => 'Please select driver'
        
]
    )]
    protected 
string $driver 'mysql';

    #[
Config_Definition(
        
typeConfig::TYPE_STRING,
        
is_requiredtrue,
    )]
    #[
Form_Definition(
        
typeForm_Field::TYPE_INPUT,
        
label'Connection name',
        
is_requiredtrue,
        
error_messages: [
            
Form_Field::ERROR_CODE_EMPTY => 'Please enter connection name'
        
]
    )]
    protected 
string $name 'default';

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

Jak vidíte, tak definice sekce konfigurace je téměř stejná, jako hlavní definice konfigurace. Jsou pouze dva drobné, ale zásadní rozdíly:

  • Třída nedědí od Jet\Config, ale od Jet\Config_Section
  • Třída sama nemá žádné hodnoty atributů. Potřebné jsou pouze definice vlastností.

Jednoduše se dá říct, že jedna konfigurace zapadá do druhé. A ano, podsekce může mít další podsekce.

Nyní již víte jak funguje definice konfigurace a jak se s tím pracuje z pohledu aplikace. Dále doporučuji kouknout na třídu Jet\Config, které je ústředním bodem celého subsystému.

Předchozí kapitola
Konfigurační systém aplikace
Další kapitola
Třída Jet\Config