Pořadí definice extensions

baraja
Nette Blogger | 29
+
0
-

Ahoj,

vždycky mě zajímalo, jestli existuje v Nette nějaký způsob, jak můžu jako autor DI extensions ovlivnit, v jakém pořadí se budou jednotlivá rozšíření kompilovat a případně jak zkontrolovat, že se pořadí kompiluje správně.

Podle pozorování to nyní funguje pravděpodobně tak, že se nejprve zkompilují všechny výchozí rozšíření, které definuje samotné jádro Nette a poté se postupně kompilují uživatelská rozšíření v tom pořadí, v jakém jsou v poli po zamergování všech neonů do sebe.

Tento přístup dává vývojáři relativně velkou volnost, ale zároveň autorovi balíčku trochu komplikací.

  1. Jak například mohu zjistit, že nějaká extension už byla zaregistrována?
  2. Existuje způsob, jak vytvořit závislost na službě z jiné extensions tak, aby se provedla i když se extensions vyhodnotí ve špatném pořadí?
  3. Může extensions o sobě říct, že musí být vyhodnocena až po nějaké jiné a případně si pořadí Nette samo v paměti prohodí?

Zejména třetí otázka by přinesla řešení řady složitých situací. Například v extension pro Doctrine definuji řadu obecných služeb, nicméně rád bych v dalších extensions (které jsou na Doctrine závislé) přidal nějaké setup parametry a podobně. Pokud se ovšem extensions zaregistrují ve špatném pořadí, tak aplikace selže.

Uživatel balíků závislosti podle názvů extensions nutně nezná, proto neví, jak moc si může dovolit jejich pořadí prohodit. Správnost totiž pozná pravděpodobně jenom podle vyhozené výjimky po selhané kompilaci.

Budu moc rád za všechny nápady, hodně by to pomohlo.

Díky moc!

Mistrfilda
Člen | 76
+
+1
-

Ahoj,

Nejsem úplně expert na složité DI extensions :D ale v poslední době jsem na problém s pořadím registrace extension v configu také narazil. Bylo to u nettrine balíčků, kdy jsem prohodil registraci pár služeb, trvalo mi chvilku než jsem to zdebugoval – dopsalo se to pak i do readme projektu zde https://github.com/…cs/README.md#… – to mi přijde jako jedna z cest. Použít jednoduše readme projektu, kde na to uživatele upozornit.

Druhá věc, co mě nepadá, je napsat jednu velkou extension, která by nahradila ty malé. Úplně jsem toto řešení nezkoumal, ale tipuji, že by se tam asi dalo hledat, jestli je nějaký balíček nainstalovaný a na základě toho, určit v jakém pořadí jednotlivé extension zaregistrovat – na toto téma jsem našel toto např. https://forum.nette.org/…lerextension

Felix
Nette Core | 1245
+
+3
-

@baraja @Mistrfilda Poradi CompilerExtension uz mame naplanovane, viz blogpost na blogu.

Toanir
Člen | 57
+
0
-

Hoj hoj,

Řeším problematiku modulů skrze extensiony a zatím se mi s vlastními extensionami daří vyhýbat problémům s pořadím načítání vyplývajícím z pořadí konfigurace.
Snažím se vždy závislosti a úkony rozložit mezi loadConfiguration a beforeCompile metody.
loadConfiguration se postarám o to, aby bylo pro danou funkcionalitu všechno připraveno a zadefinováno uvnitř ContainerBuilderu. O samotný poslepování se potom starám v beforeCompile.

Pokud chápu správně životní cyklus kompilace kontejneru, při beforeCompile by měl ContainerBuilder obsahovat definice ze všech ostatních extension a ty bys měl být schopný si závislost vytáhnout pomocí metody getByType / findByType. Alternativně si můžeš do konfigurace nechat poslat název služby, kterou chceš dekorovat / předat.

Nepomohlo by ti přesunout část konfigurace kompilace do beforeCompile?

2bfree
Člen | 248
+
0
-

Řešil jsem podobná témata.

Nejprve jsem narazil na potřebu si zaregistrovat nějakou „obecnější“ doprovodnou službu, která mohla a nemusela být již zaregistrovaná z jiné extension.

K tomu slouží helper setupServiceAlias, který nastaví pro danou extension alias pro případnou již existující službu, aby s tím šlo dále pracovat, jako by byla vytvořená lokálně. Nebo to vrátí false, tedy že služba daného typu ještě neexistuje, pak je možné (a potřeba) službu registrovat.

Použití viz například zde

Po čase jsem ale narazil na omezení, že je potřeba navěsit službu opravdu v konkrétním pořadí (před / za) jinoujiž registrovanou službu.

K tomu slouží registration helpery processRegisterAfter a processRegisterBefore.
Použití viz například zde

Snad to alepoň takto pomůže

Felix
Nette Core | 1245
+
0
-

V nove verzi jsem se zameril na poradi extensions, resp. zjednoduseni, aby to nebylo potreba.

Priklad z https://github.com/…ine-skeleton

extensions:
	console: Contributte\Console\DI\ConsoleExtension(%consoleMode%)

	nettrine.dbal: Nettrine\DBAL\DI\DbalExtension
	nettrine.orm: Nettrine\ORM\DI\OrmExtension

nettrine.dbal:
	debug:
		panel: %debugMode%

	connections:
		default:
			driver: %postgres.driver%
			host: %postgres.host%
			port: %postgres.port%
			dbname: %postgres.dbname%
			user: %postgres.user%
			password: %postgres.password%
			charset:  UTF8
			serverVersion: 15.0.0

		second:
			driver: %mariadb.driver%
			host: %mariadb.host%
			port: %mariadb.port%
			dbname: %mariadb.dbname%
			user: %mariadb.user%
			password: %mariadb.password%
			charset:  UTF8
			serverVersion: 10.10.0

nettrine.orm:
	managers:
		default:
			connection: default
			mapping:
				App:
					type: attributes
					dirs: [%appDir%/Domain/Database]
					namespace: App\Domain\Database
		second:
			connection: second
			mapping:
				App:
					type: attributes
					dirs: [%appDir%/Domain/Database]
					namespace: App\Domain\Database