DI – Kolekcia sluzieb pre factory

duskohu
Člen | 778
+
0
-

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
+
0
-

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
+
0
-

@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

Martk
Člen | 661
+
+1
-

V nette 2.4 bych stále používal arachne/service-collections a v 3.0 bych přešel na di

Doufám, že jsem to pochopil správně, co potřebuješ.

Milo
Nette Core | 1283
+
+4
-

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
+
0
-

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?

Milo
Nette Core | 1283
+
0
-

A co potřebuješ, aby ta extension dělala? V úvodu jsi psal, že to chceš pro službu RouterFactory

duskohu
Člen | 778
+
0
-

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
+
+2
-

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),
			]);
}