DI – Kolekcia sluzieb pre factory
- duskohu
- Člen | 778
Ahojte snazim sa v nette 2.4 vyriesit tento problem:
Mmam factory, do ktorej potrebujem dostat vsetky sluzby implementujuce
IRouter
a zavolat nad nimi metodu setRouter()
V extension zaregistrujem RouterFactory
, konkretne sluzby
routrov ktore mozem mat n pocet, ale neviem ako dostat do
RouterFactory
tie sluzby. neviete mi poradit ako na to?
interface IRouter
{
/**
* @param RouteList $routeList
* @return void
*/
public function setRouter(RouteList $routeList);
}
class RouterFactory
{
use SmartObject;
/** @var IRouter[] */
protected $routerParts;
/**
* @param IRouter[] $routerParts
*/
public function __construct(array $routerParts)// sem potrebujem vsetky sluzby implementujuce IRouter
{
$this->routerParts= $routerParts;
}
/**
* @return RouteList
*/
public function create()
{
$routeList = new RouteList();
foreach ($this->routerParts as $item) {
$item->setRouter($routeList);
}
return $routeList;
}
}
// jedna zo sluzieb Routru
class Router implements IRouter
{
/**
* @param RouteList $routeList
* @return void
*/
public function setRouter(RouteList $routeList)
{
$routeList[] = new Route(...);
}
}
// extension
$builder->addDefinition($this->prefix('router'))
->setFactory(Router::class);
$router = $builder->getDefinition('router');
$router->setFactory(array(
new Statement(RouterFactory::class),
'create'
));
- Petr Parolek
- Člen | 455
Ahoj, o co ti jde? Pokud ti jde o modulární aplikaci s DI extension, vyřešil jsem to přes extension webchemistry/router https://github.com/…istry/router#… .
- duskohu
- Člen | 778
@ppar Ano ide mi o moluranost, ale nie len o router ale mam viacero
takychto facory napr. Navigation, Security …
Doteraz som pouzival arachne/service-collections
ale ta uz bude casom zastarala, tak hladam nahradu
- Milo
- Nette Core | 1283
V Nette DI 3 bude stačit, když konstruktor RouterFactory
oanotuješ tak, jak máš. Tedy
/** @param IRouter[] $routerParts **/
a DI kontejner už předá
pole služeb. Pokud neoanotuješ, v NEONu budeš moci ručně:
services:
- RouterFactory( types(IRouter) )
V Nette 2.4 můžeš types()
emulovat. Nadefinuj si
funkci:
function types(string $type, Nette\DI\Container $container): array
{
return array_map(function (string $name) use ($container) {
return $container->getService($name);
}, $container->findByType($type));
}
A v NEON konfiguraci:
services:
- RouterFactory( ::types(IRouter) )
S přechodem na Nette DI 3 jen odstraníš dvojtečky a definici funkce.
- duskohu
- Člen | 778
Milo napsal(a):
V Nette DI 3 bude stačit, když konstruktor
RouterFactory
oanotuješ tak, jak máš. Tedy/** @param IRouter[] $routerParts **/
a DI kontajner už předá pole služeb. Pokud neoanotuješ, v NEONu budeš moci ručně:services: - RouterFactory( types(IRouter) )
V Nette 2.4 můžeš
types()
emulovat. Nadefinuj si funkci:function types(string $type, Nette\DI\Container $container): array { return array_map(function (string $name) use ($container) { return $container->getService($name); }, $container->findByType($type)); }
A v NEON konfiguraci:
services: - RouterFactory( ::types(IRouter) )
S přechodem na Nette DI jen odstraníš dvojtečky a definici funkce.
@Milo dakujem, parada, a ako to prosim ta zapisem v Extension?
- duskohu
- Člen | 778
Milo napsal(a):
A co potřebuješ, aby ta extension dělala? V úvodu jsi psal, že to chceš pro službu
RouterFactory
…
Je vseobecne pre kolekcie, ale nevedel som ako ten zapis napisat v php. Skusil som to takto, funguje to, neviem ci je aj cistejsi zapis.
$router = $builder->getDefinition('router');
$router->setFactory(
array(
new Statement(
RouterFactory::class,
array(new PhpLiteral('types("NasExt\Framework\Application\Router\IRouter", $this)'))
),
'create'
)
);
- Milo
- Nette Core | 1283
Aha. No, pokud si chceš vyzobnout služby daného typu z kontejneru
v extension, types()
na to nepotřebuješ. Napsal bych to asi
takhle, ale ber to s rezervou, protože nevím, na co to přesně
potřebuješ.
public function loadConfiguration()
{
$builder = $this->getContainerBuilder();
$factory = $builder
->addDefinition('routerFactory')
->setType(RouterFactory::class);
$builder
->addDefinition('router')
->setType(Router::class)
->setFactory([$factory, 'create']);
}
public function beforeCompile()
{
$builder = $this->getContainerBuilder();
$builder
->getDefinition('routerFactory')
->setArguments([
$builder->findByType(IRouter::class),
]);
}