Význam a použití DI extension
- jstas
- Člen | 4
Zdravím!
Jako nezkušený programátor nedokážu rozpoznat, zda nepokládám
stupidní dotaz, nicméně i přes veškerou svou snahu jsem nedokázal
přijít na to, jakým způsobem fungují extensions
v konfiguračním souboru config.neon
. Možná mám problém se
samotným pochopením významu extensions
.
V rámci své aplikace, na které se s Nette seznamuji, jsem se rozhodl,
že bych do konfiguračního souboru uložil jména některých tabulek
z databáze (na tom v podstatě nesejde, mohlo to být cokoliv jiného).
Cílem bylo v tomto souboru definovat (v podstatě) konstanty, které by se
daly používat napříč projektem a v případě změny názvu tabulky se
kód upravoval pouze na jednom místě. Rozšířil jsem tedy soubor
config.neon
o následující kód.
extensions:
tables: App\Config\Extensions\TablesExtension
tables:
# Config
table_users: users_cs
table_articles: articles_cs
Kód extension
pak vypadá následovně.
<?php
namespace App\Config\Extensions;
use Nette\DI\CompilerExtension;
class TablesExtension extends CompilerExtension {
public $config;
public function loadConfiguration() {
$this->config = $this->getConfig();
}
}
Z vysvětlení a příkladů (v dokumentaci)
mi není jasné, jak potom k datům z extension
(očekávané v
$config
) přistoupím. Pokusím-li se TablesExtension
dostat do nějaké třídy v aplikaci pomocí konstruktoru jako DI službu,
nastane Nette\DI\ServiceCreationException
, tedy toto.
Service 'settingsManager' (type of App\Managers\Settings\SettingsManager): Service of type App\Config\Extensions\TablesExtension needed by $tables in App\Managers\BaseManager::__construct() not found. Did you register it in configuration file?
Pokud TablesExtension
přidám v config.neon
i mezi services
, předaná instance v BaseManager
data (názvy tabulek) neobsahuje. To považuji už jen za výstřel do tmy.
Skutečně netuším, jak správně tedy extensions kdekoliv v aplikaci
využít. Předpokládal jsem, že blok kódu (níže), který je do metody
loadConfiguration()
přidáván v dokumentaci (na níž vede odkaz
výše), nebudu potřebovat, neboť žádné prefixy nevyužívám a žádné
další služby uvnitř této nevyužívám.
$builder = $this->getContainerBuilder();
$builder->addDefinition($this->prefix('articles'))
->setFactory(App\Model\HomepageArticles::class, ['@connection'])
->addSetup('setLogger', ['@logger']);
Nenašel by se zde prosím někdo, kdo by mi pomohl do problému trochu více zabřednout? Zajímá mě, jestli na problém pohlížím zcela špatně, nebo jen někde dělám nějakou hloupou chybu.
Mnohokrát Vám předem děkuji.
S pozdravem Honza
- Šaman
- Člen | 2667
Na tohle DI extension vůbec nepotřebuješ. Jestli chceš jen načítat
parametry z configu, tak si vytvoř nějakou třídu, třeba
TableConfig
, která v konstruktoru přijme pole parametrů,
ideálně si je dokáže zvalidovat a potom je pomocí nějakých
getterů dává.
V configu si v sekci parameters
vytvoříš pole
tables
a pak toto pole předáš té třídě. Voila, máš
třídu, která dostala z configu názvy tabulek a tu si injectuješ kam
potřebuješ.
parameters:
tables:
table_users: users_cs
table_articles: articles_cs
services:
- App\…\TableConfig(%tables%)
class TableConfig
{
/** @var array */
protected $tables;
/**
* @param array
*/
public function __construct(array $tables)
{
$this->tables= $tables;
}
/**
* @param string
* @return string
*/
public function getTable($name)
{
return $this->tables[$name];
}
}
P.S. Je to nástřel bez namespaces, bez validace, případné traity SmartObject a bez PHP7 typů. Je to upravená funkčni ukázka z jednoho staršího projektu.
P.P.S. Jinak extension jsem nikdy nepotřeboval sám psát a mám dojem, že
je to vyšší dívčí – když potřebuješ s třidama v DI kontejneru
nějak dál manipulovat. Třeba DibiExtension umožňovala zápis databáze do
vlastní sekce dibi
, automaticky vytvořila třídy Dibi a
konfiguraci jim předala a ještě to celé zaregistrovala do Tracy panelu,
takže se tam ukazovaly dotazy do db. Tedy dělala nějakou magii na pozadí.
Bez použití extension se musely údaje o připojení k DB zapsat do sekce
parameters, pak v services zaregistrovat správné třídy a parametry jim
předat a TracyPanel se dal zaregistrovat taky ručně.
Takže pokud chceš transparentní zápis a týká se to jen tvé aplikace, použij nějaký způsob jako jsem ukázal. Extension je opravdu rozšíření DI kontejneru ve smyslu přidat mu nějakou novou funkci, nebo syntax. Ty myslím potřebuješ obyčejnou práci s parametry, na což je ten DI kontejner a zápis v configu dělaný.
Editoval Šaman (14. 3. 2020 2:15)