Načítání tříd se stejným jménem (jiným namespace) jako služby v configu
- ondrapech
- Člen | 49
Ahoj, potřeboval bych proadit. Mám aplikaci s více moduly pro různé země. V každém modulu řeším objednávky ale vždy trochu jinak. Tak jsem chtěl mít nějak jako App/Models/OrdersModel a potom App/AdminModule/CzechModul/Models/OrdersModel, App/AdminModule/PolandModule/Models/OrdersModel, …
Všechny třídy jsem chtěl zaregistrovat jako služby v configu, k tomu používám contributte/di
autoload:
resources:
App\Models\:
paths: [%appDir%/models]
excludes: [App\Models\MyAuthenticator, App\Model\AuthorizatorFactory]
App\AdminModule\CzechModule\Models\:
paths: [%appDir%/AdminModule/CzechModule/models]
App\AdminModule\PolandModule\Models\:
paths: [%appDir%/AdminModule/PolandModule/models]
Při spuštění mi DI vyhodí vyjímku Nette\DI\ServiceCreationException
Service ‚application.10‘ (type of
App\AdminModule\CzechModule\Presenters\OrdersPresenter): Multiple services of
type App\Models\OrdersModel found:
autoload._App_AdminModule_CzechModule_Models_.1,
autoload._App_AdminModule_PolandModule_Models_.1 (needed by $ordersModel in
__construct())
Nevíte někdo jak to vyřešit? Nemáte s tím zkušenoti? Moc díky.
- ondrapech
- Člen | 49
h4kuna napsal(a):
Na ten model/y si udělej továrnu, kde budeš mí logiku s tím jaký model použít a pak vracej jeho instanci, klidně si tam injektni kontejner, aby jsi mohl pohodlně získávat instance.
Edit: Pokud ti toto popostrčení nestačí, tak napiš.
To přece úplně neřeší můj problém? já Vždy vím jakou třídu budu potřebovat, presenter je zvlášť český a zvlášť zahraniční, vždy v jiném modulu. např.
public function __construct(App\AdminModule\CzechModule\Models\OrdersModel $ordersModel)
{
parent::__construct();
$this->ordersModel = $ordersModel;
}
// A
public function __construct(App\AdminModule\PolandModule\Models\OrdersModel $ordersModel)
{
parent::__construct();
$this->ordersModel = $ordersModel;
}
//Pak mám ty třídy např:
namespace App\AdminModule\PolandModule\Models
class OrdersModel extends \App\Models\OrdersModel
{
protected $ordersTable = 'poland_orders'
}
...
Vždy si načítám konkrétní třídu, tak nechápu, kde je problém… Nebo možná nechápu, jak to myslíš. Továrnám sice ne úplně rozumím ale pdole mě bych tenhle problém řešil v té továrně, ne? Tam stačí že mám ty třídy takhle vytvořené i když je nepoužuju aby tam byl ten problém.
Myslíš jako, že bych měl tu továrnu zaregistrovanou jako službu a ta by
vracela instanci té třídy, tzn. ty třídy by nebyly jako služby ale
normálně bych si je vracel
return new \App\AdminModule\.....\OrdersModel($database)
?
Editoval ondrapech (26. 7. 2019 13:50)
- Michal Hlávka
- Člen | 190
Ja to ted zazil taky napric modulama, kdy dva presentery dedily od jednoho abstraktniho. Nemel jsem cas to vic resit, hodil jsem kod do traity, coz nebylo idealni reseni jak pro me, tak v tomhle pripade i pro tebe.
Editoval Michal Hlávka (26. 7. 2019 14:24)
- ondrapech
- Člen | 49
MajklNajt napsal(a):
@ondrapech skontroluj, či v niektorej triede (presenteri alebo modelovej…) nemáš vyžadovanú v contructore tú pôvodnú triedu
App/Models/OrdersModel
druhá vec – v tomto prípade by bolo možno fajn použiť dekorovanie namiesto dedenia…
Tak sem prohledal celý projekt, nikde nepoužívám samotnou rodičovskou třídu a stejný problém :/ Co myslíš dekoráváním? Jak na to v kódu?
- Polki
- Člen | 553
Proč nepoužíváš nějaký translátor místo dvou různých jazykových
modulů?
Máš pro Polsko (krom jazyka) tu aplikaci jinou, než pro ČR?
Pokud jsou aplikace stejné, akorát s jiným jazykovým nastavením doporučuji translator.
Vzhledem k tomu, že píšeš, že tam máš trochu jinak řešenou
objednávku, tak záleží jak moc jinak to složité je.
Každopádně zde taky nevidím důvod použít Moduly. Stačí, když si
vytvoříš interface např IOrderModel, který bude mít metody pro práci,
které potřebuješ, například add(), update(), remove() atd…
Pak budeš mít dvě třídy, které se budou jmenovat CzechOrderModel a PolandOrderModel. No a obě budou implementovat interface IOrderModel, kde bude vlastní logika pro každý jazyk jiná. Pak budeš mít továrnu, která bude mít metodu create($language) a vrátí ti objekt instance IOrderModel, který reálně bude buď CzechOrderModel, nebo PolandOrderModel, podle toho, jaký jazyk pošleš v $language oné továrně. No a pak ať ti přijde jakýkoli z oněch 2 modelů, tak s nimi pracuješ podle onoho interface, tedy stejně pro všechny jazyky, jen se bude lišit vnitřní implementace. :)
- h4kuna
- Backer | 740
ondrapech napsal(a):
Myslíš jako, že bych měl tu továrnu zaregistrovanou jako službu a ta by vracela instanci té třídy, tzn. ty třídy by nebyly jako služby ale normálně bych si je vracel
return new \App\AdminModule\.....\OrdersModel($database)
?
Přesně takhle jsem to myslel, jen bych všechny modely dal autowired: no, a do továrny bych si poslal Container a pak bych modely vytahoval z kontejneru abych v modelech mohl použít DI.
Ale když máš konkrétní třídu pro konkrétní modul/presenter, tak to funguje, teď jsem si to zkusil na sandboxu. Nemáš náhodou někde v konstruktoru právě toho předka? App\Models\OrdersModel to pak by byla potřeba továrna.
Editoval h4kuna (29. 7. 2019 13:01)
- Oli
- Člen | 1215
Podle mě hledáš něco takového:
- EntityService\OrdersModel
orderEditorService:
create: EditorService\OrdersModel
autowired: self
orderPolandModule:
create: OrderPolandModule\OrdersModel
autowired: self
class EntityService\OrdersModel {}
class EditorService\OrdersModel extends EntityService\OrdersModel {}
class PolandModule\OrdersModel extends EditorService\OrdersModel {}