Nette 3.0 – vytvoření služby s dynamickými parametry

juklicek
Člen | 12
+
0
-

Ahoj, aktuálně migrujeme rozsáhlou aplikaci na nette3. Narážíme na problém s vytvářením service s dynamickými parametry. Dříve jsme v configu DI měli takto:

services:
  my:
    class: App\MyService
    parameters: [a]
    arguments: [%a%]

Nette 3 nám hlásí:
Nette\DI\InvalidConfigurationException: Unexpected option ‚services › my › parameters‘

zatím marně pátráme co s tím.

Děkuji za pomoc

David Grudl
Nette Core | 8227
+
0
-

A co by to mělo přesně dělat? Resp. jak s takovou službou pak pracujete?

juklicek
Člen | 12
+
0
-

:) Bál jsem se této odpovědi.
No používáme to, když je potřeba již za běhu aplikace vytvořit službu s různými parametry.
Tzn. zjednodušeně, když pak voláme

$service1 = $this->container->createService('my', 'neco1');
$service2 = $this->container->createService('my', 'neco2');

získám servis jednou s parametrem neco1 a jednou s neco2
V reálu má většinou servis v konstruktoru více závislostí – x běžných, a třeba jen jeden ten dynamický, který je třeba měnit za běhu.

services:
  my:
    class: App\MyService
    parameters: [userID]
    arguments: [@someService1, @someService2, %userID%]

pak šlo za běhu získat instanci s extra parametrem:

$service = $this->container->createService('my', '123');

Díky za tip!

CZechBoY
Člen | 3608
+
0
-

A co si na tu sluzbu udelat tovarnu? Nette umi generovane tovarny pres interface, zavislosti poresi samo.

juklicek
Člen | 12
+
0
-

No jasně, přes továrnu je to asi čitelnější postup, nám jde ale teď o překlopení stávající velké aplikace.. Takže hledáme nejjednodušší postup… Máme to takto skoro u 500ti servisů :/

Nějaký tip na co nejminimalističtější oficiální obdobu tohoto? :)

Díky

juklicek
Člen | 12
+
0
-

@CZechBoY dík za tip – to nám třeba pomůže při samotném refactoringu, ale stále si nejsme jistí, na co to refaktorovat.

Nette umí (umělo) pomáhat s továrničkami také tímto způsobem:
https://doc.nette.org/…tion/factory

Ale řekněte mi, jak komponentě RegistrationControl (do konstruktoru), předám metodou RegistrationControlFactory->create(xy) ten parametr xy?

Tam dříve zase fungovali ty parameters, ale nette 3.0 to odmítá..:/

Kdo používá v nette komponenty tak to musí řešit pořád … nebo mi něco uniká? :)

Díky!

janpecha
Backer | 75
+
0
-

Od Nette 2.3 (či tak nějak) si to dokáže ten dynamický parametr zpracovat samo – tj. pro RegistrationControlFactory->create(xy) stačí něco jako:

services:
	- IRegistrationControlFactory
interface IAbcFactory
{
	function create($xy);
}

class RegistrationControl
{
	public function __construct($xy, SomeService1 $someService1, SomeService2 $someService2)
	{}
}

Takže v configu není nutné to parameters uvádět.

David Grudl
Nette Core | 8227
+
0
-

juklicek napsal(a):

Tzn. zjednodušeně, když pak voláme

$service1 = $this->container->createService('my', 'neco1');
$service2 = $this->container->createService('my', 'neco2');

Rozumím.

Tomuhle použití kontejneru se říká Service Locator a Nette se mu snaží od verze 2.0 vyhýbat a nahrazovat za DI. Hlavní rozdíl je v tom, že místo volání metody nad neurčitým containerem, kde není zcela jasné, co umí a vrací za objekt, se volají metody nad jasně definovanou třídou, kde je tedy evidentní, co přesně vrací. Takovou třídu umí DI vygenerovat, stačí vytvořit pouze její interface. Třeba jak psal @janpecha.

U všech těch 500 služeb je potřeba předávat vlastní parametry, tj. druhý a další parameter u createService()?