Načítání tříd se stejným jménem (jiným namespace) jako služby v configu

ondrapech
Člen | 49
+
0
-

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.

h4kuna
Backer | 740
+
0
-

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š.

Editoval h4kuna (24. 7. 2019 15:26)

ondrapech
Člen | 49
+
0
-

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

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)

MajklNajt
Člen | 470
+
0
-

@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…

ondrapech
Člen | 49
+
0
-

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

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

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

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 {}