Chyba Multiple services of type Nette\ComponentModel\IContainer

Upozornění: Tohle vlákno je hodně staré a informace nemusí být platné pro současné Nette.
nat
Člen | 12
+
0
-

Zdravím,

mohl by mi prosím někdo poradit v čem je zakopaný pes? Přidávám komponenty pomocí injectu do presenteru.

Mám hierarchii komponenet

abstract class BaseControl extends \Nette\Application\UI\Control
class FacebookLoginControl extends BaseControl
class ProfileAsideControl extends BaseControl

Pokud dám do configuračního souboru jen jednu komponentu, pak je vše v pořádku. V případě, že přidám i druhou vyhodí mi nette chybu:
neon

services:
    facebookLoginComponent: Components\Controls\FacebookLoginControl
    profileAsideControl: Components\Controls\ProfileAsideControl

Chyba

Nette\DI\ServiceCreationException

Service 'profileAsideControl': Multiple services of type Nette\ComponentModel\IContainer found: facebookLoginComponent, profileAsideControl

Editoval nat (21. 4. 2013 18:55)

enumag
Člen | 2118
+
0
-

Zřejmě máš špatný typ v té inject* metodě.

Majkl578
Moderator | 1364
+
0
-

Komponenta by rozhodně neměla být službou. Udělej si na ni factory a předávej si ji.

nat
Člen | 12
+
0
-

enumag napsal(a):

Zřejmě máš špatný typ v té inject* metodě.

Ne Inject metoda má správný typ

public function injectAsideComponents(
            \Components\Controls\ProfileAsideControl $profilAside) {
        $this->profilAside = $profilAside;
    }

Majkl578 napsal(a):

Komponenta by rozhodně neměla být službou. Udělej si na ni factory a předávej si ji.

No právě, že mám na projektu nette 2.0.6 a injectování komponent jako továren podporuje až 2.1 – pokud se nepletu?

Editoval nat (21. 4. 2013 22:47)

enumag
Člen | 2118
+
0
-

Automatické generování factories je až ve 2.1, ale jinak si factory jako službu můžeš přidat už ve 2.0. Jen ji budeš muset sám napsat.

Jo a tu chybu to hází kvůli konsturktoru jednoho z rodičů.

Editoval enumag (21. 4. 2013 22:52)

Majkl578
Moderator | 1364
+
0
-

nat napsal(a):

No právě, že mám na projektu nette 2.0.6 a injectování komponent jako továren podporuje až 2.1 – pokud se nepletu?

Není nic jednoduššího než si napsat vlastní factory (zde příklad s 1 závislostí):

<?php

class SomeControlFactory extends Nette\Object
{
	/** @var Foo */
	private $foo;

	public function __construct(Foo $foo)
	{
		$this->foo = $foo;
	}

	/**
	 * @return SomeControl
	 */
	public function create()
	{
		return new SomeControl($this->foo);
	}
}

V configu si pak registruješ tuto factory jako službu:

services:
    - SomeControlFactory

V presenteru injectneš tuto create:

/** @var SomeControlFactory */
protected $someControlFactory;

public function injectSomeControlFactory(SomeControlFactory $someControlFactory)
{
	$this->someControlFactory = $someControlFactory;
}

A v továrničce si od ní necháš komponentu vytvořit:

protected function createComponentSome()
{
	return $this->someControlFactory->create();
}
hAssassin
Člen | 293
+
0
-

@Majkl578 > hoj, diky za pekny navod, protoze si konecne zacinam myslet ze chapu, k cemu je to dobre. ale preci jenom, mohl bys mi please explicitne rict, k cemu to skutecne dobre je? misto toho abych si tu komponentu vytvarel sam az v tovarnicce v presenteru? diky…

Majkl578
Moderator | 1364
+
0
-

hAssassin napsal(a):

mohl bys mi please explicitne rict, k cemu to skutecne dobre je? misto toho abych si tu komponentu vytvarel sam az v tovarnicce v presenteru? diky…

Představ si komponentu, která má závislost na 3 službách. Abys ji mohl v presenteru instanciovat, musel bys prvně do presenteru předat všechny ty 3 služby a následně je při instanciaci komponenty předat jí. Teď si představ následující situace:

  • Chci komponentu použít na více místech (protože je to komponenta, už z principu se to přímo vybízí), např. v 5 presenterech – musel bych tohle udělat na všech místech.
  • Potřebuji komponentě přidat závislost na další službu – musel bych najít všechny presentery používající ji, ve všech si předat tu novou službu a všude ji nově předávat.
  • Celé se to ještě víc zamotá, když budu chtít naši komponentu použít uvnitř jiné komponenty. :)

Tím, že si na ni udělám továrničku a pak předávám pouze ji, nemusím řešit žádný z výše uvedených problémů. Ať už komponentě přidám závislost nebo ne, továrna bude pořád stejná (samozřejmě že fyzicky nebude, protože tam přibude např. závislost, ale pro účely DI (autowire) a následného vytvoření samotné komponenty se nic nemění).

hAssassin
Člen | 293
+
0
-

@Majkl578 > pecka, tak sem to pochopil spravne. Jeste jednou diky za super priklad a vysvetleni. Porad mi totiz utikala pointa toho, proc je to tak super a je fakt ze to super je :)