DI více service, které implementují jednu interface

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

Jde nějak injectnout službu, která implementuje interface? Ale těch služeb bych chtěl mít více. Konkrétně 2.

Myslel jsem si, že když nastavím autowired: false, tak to půjde, ale stejně to na mě řve, že se mu to nelíbí.

Konkrétně to chci pro cachovaný a necachovaný dotazy do databáze. Představoval jsem si to nějak tak, že když:

vypnu cache

tak se mě zaregistruje DomainRepository jako služba.

class DomainRepository extends EntityRepository implements IDomainRepository {}

Zapnu cache

tak se mě DomainRepository zaregistruje taky jako služba, ale s autowired: false a zaregistruje se mi další třída CachedDomainRepository.

domain:
	class: DomainRepository
	autowired: false
- CachedDomainRepository(@domain)
class CachedDomainRepository implements IDomainRepository
{

  /**
   * @var Cache
   */
  private $cache;

  /**
   * @var DomainRepository
   */
  private $domainRepository;

  public function __construct(IStorage $storage, DomainRepository $domainRepository)
  {
    $this->cache = new Cache($storage, 'domain');
    $this->domainRepository = $domainRepository;
  }
}

Otázky:

Jde to nějak?
Proč to na mě řve, že to implementují 2 služby, když jedna je neautowirovaná?
Jak řešíte zapínání, vypínání cache vy?

Díky za tipy.

newPOPE
Člen | 648
+
0
-

Preco tam tu cache potrebujes? Ak tak daj realny priklad.

CZechBoY
Člen | 3608
+
0
-

Ja to teda delam jinak… Predam si cache primo do repozitare atam cachuju vzdy (devnull storage to sice neuchova, ale to uz me nezajma).

Oli
Člen | 1215
+
0
-

No protože chci cachovat dotazy do databáze :)

class DomainRepository extends EntityRepository implements IDomainRepository {

	public function fetchBySomtething($something){
		return $this->findOneBy(['something'=> $something]);
	}
}
class CachedDomainRepository implements IDomainRepository
{

  /**
   * @var Cache
   */
  private $cache;

  /**
   * @var DomainRepository
   */
  private $domainRepository;

  public function __construct(IStorage $storage, DomainRepository $domainRepository)
  {
    $this->cache = new Cache($storage, 'domain');
    $this->domainRepository = $domainRepository;
  }

	public function fetchBySomtething($something){
		return $this->cache->load($something, function(& $dependencies) use ($something) {
    		return $this->domainRepository->fetchBySomtething($something);
		});

	}

}

No a chci to mít možnost vypnout, nebo vypnout jen jednu extension nebo jen jeden repositar (to bych prehodil jen rucne)…

Je to blbost?

CZechBoY
Člen | 3608
+
0
-

Vypneš to tak, že předáš devnull storage tý službě.

services:
	- class: CachedDomainRepository
      arguments: [storage: Nette\Caching\Storages\DevNullStorage]
Oli
Člen | 1215
+
0
-

Hm. to by skoro šlo.

Ještě jsem teď narazil, že nejsem schopnej do repository si předat cache. Ta repository je jako repository uvedena u entity. Já ji zaregistruju jako službu a předají se jí závislosti. Problém je, že nevím jak se jí ty závislosti předají, protože Doctrine\Orm\Mapping\ClassMettadata není zaregistrováno jako služba, takže já nejsem schopnej v potomku EntityRepository použít constructor. Zkoušel jsem to přes set metodu, ale to taky nešlo.

Na jaký úrovni to cachuješ, přímo v repository? Používáš repositoryClass u entity?

/**
 * @ORM\Entity(repositoryClass="DomainRepository")
 */
class Domain
Oli
Člen | 1215
+
0
-

Spíš by mě ale zajímalo, proč nemůžu mít víc služeb, který implementujou stejné rozhraní a zapnutý autowire jen na jedné a ostatní předávat v configu? To by mělo technicky jít, nebo ne?

David Matějka
Moderator | 6445
+
0
-

to jde. asi delas neco blbe. jak presne vypada chybova hlaska?

CZechBoY
Člen | 3608
+
0
-

@Oli nepouzivam doctrine ani orm. Ve sluzbe si injectnu repo a to pak pouzivam, nezavisle jestli to bere z cache nebo odkud…

Oli
Člen | 1215
+
0
-

@DavidMatějka hláška vypadá takhle:

Service ‚134_Core_Nette_Managers_DomainManager‘: Multiple services of type Core\Entities\Domains\Repositories\IDomainRepository found: 140_Core_Entities_Domains_Repositories_DomainRepositoryDecorator, domainRepository

jak to mám v configu a jak vypadají ty třídy je v prvním postu. Očekával bych, že DomainRepositoryDecorator se bude normálně autowirovat podle interface a DomainManager se vloží jen tam, kam ho vložím ručně.

Jen doplním tu třídu, která vyžaduje tu službu:

class DomainManager
{
	public function __construct(
		IDomainRepository $domainRepository,
		Session $session,
		Request $request,
		DomainProvider $domainProvider
	)
}

Editoval Oli (25. 11. 2016 15:24)

David Matějka
Moderator | 6445
+
0
-

vypada to, ze tam mas nekde sluzbu pojmenovanou domainRepository

Oli
Člen | 1215
+
0
-

@DavidMatějka mám. jak jsem to různě zkoušel, tak jsem to domain přejmenoval na domainRepository.

Takže to teď vypadá takhle (respektive vypadalo, mám to zase jinak :-))

domainRepository:
    class: Core\Entities\Domains\Repositories\DomainRepository
    autowired: false
- Core\Entities\Domains\Repositories\DomainRepositoryDecorator(@domainRepository)

Nicméně tím to není.

David Matějka
Moderator | 6445
+
+1
-

hm, ono to asi nebude kompatibilni s kdyby magii, ktera ty sluzby odebira a pak zas pridava… https://github.com/…xtension.php#L713

Oli
Člen | 1215
+
0
-

aha. nějakej návrh, nápad jak to obejít? :) Nebo to o co se snažím je bad practice?