Databázové resource pro moduly, použitelné na více místech
- Lebus
- Člen | 3
Zdravím,
už mi to trvá fakt dlouho, tak se zkusím zeptat tady.
Moje aplikace poběží na jedné doméně, kde se bude moct přihlašovat
neomezený počet uživatelů. Každý přihlášený uživatel má vlastní
databázi a abych nemusel pro každého uživatele vytvářet nové připojení
do DB, tak sem se rozhodl jít cestou jednoho připojení. A nyní se
dostávám k jádru pudla. Vytvořil jsem si základní Resource třídu:
Od této třídy dědí moje moduly, například modul Osoby viz:
Všimněte si použití
->from($this->fromProject('persons'))
(proto potřebuji to
dědění od té základní třídy, jelikož metoda
fromProject mi vrátí správnou databázi dle identity
přihlášeného uživatele).
Potud je vše ještě OK, až na to, že si každý resource musím definovat
v config.neon, ale to je to nejmenší co mě nyní trápí. Co mě trápí je
to, že mám další resource AccountResource a tento resource
bych chtěl použít pro Authenticator, ale při použití mi
to napíše:
Nette\InvalidStateException
Circular reference detected for services: application.5, security.user,
authenticator, authResource.
Což mě už vytáčí a nevím co s tím :-D. Možná by bylo nejlepší mít nějakou factory ResourceFactory a nejlépe, kdyby přes tuhle ResourceFactory šli vkládat závislosti v config.neon například něco takového:
A pak bych si mohl do presenteru vždy zavolat pouze ResourceFactory a z tý bych si vytáhl resource, který potřebuji (PersonsResource, CompaniesResource …), ale ani tato factory mi nejde udělat, jelikož to končí na stejné chybě **Circular reference detected … **
Snad sem to popsal dost srozumitelně, za každý tip nebo navedení na správnou cestu děkuju :-)
- pata.kusik111
- Člen | 78
application.5 je s největší pravděpodobností tvoje
AccountResource
. Ta potřebuje ke svému vytvoření
User
, protože dědí od DatabaseResource
a ta ve
svém konstructoru injectuje User
. User
ke svému
vytvoření potřebuje IAuthenticator
(viz api pro 2.3.7). Tak se
kontejner snaží vytvořit instanci IAuthenticator
. A jak
píšeš, tvoje implementace vyžaduje AccountResource
. To je jak
se dostáváš k té kruhové závislosti.
A jak tedy na to?
Nejlepší řešení je tuhletu kruhovou závislot nějak rozbít. Jiný design,
který ji nevyžaduje, zvážit, jestli jsou všechny závislosti opravdu
potřeba.
Jiné řešení je mít nějakou ještě úplně jinou třídu, která
tuhletu skupinu tříd vytvoří.
Pak některé závislosti nemusí být přímo v konstruktoru, protože
můžeš zajistit, že je tam injectneš až po tom, co se objekt vytvoří, ale
ještě před tím, než ho dostane do rukou kdokoliv jiný.
- Lebus
- Člen | 3
Tohle jsem nakonec tedy vyřešil tím, že jsem si DatabaseResource ještě rozdělil nyní DatabaseResource dědí od BaseResource, který dostává pouze DibiConnection a u AccountResource dědí pouze od toho BaseResource
viz:
a nový DatabaseResource:
Což funguje a to je super! :-)
Ale mám ještě malej dotaz. Tímto způsobem mi vznikne řada resourců (Persons, Account, Companies, Tasks, …) a všechny musím zapsat do config.neon, nešlo by to nějak přepsat do factory? Zkoušel jsem to, ale to mi pak vyhodí starou známou Circular reference detected…
- jiri.pudil
- Nette Blogger | 1034
Mohl by sis teoreticky napsat rozšíření compileru, které ti ty služby nějak dynamicky najde a zaregistruje, ale připadá mi to jako kanón na vrabce – zas tolik jich snad nemáš, abys je v configu nevypsal; navíc s pluginem jde všechno snáz :)