Rozšíření repository z extension o nové metody
- Oli
- Člen | 1215
Mám repository v modulu. Abych byl konkrétní (s tím se líp pracuje): Mám UserModule, v něm UsersRepository. Pro konkrétní projekt bych potřeboval aby ten modul měl další metody. Ideálně tak, abych jen přidal třídu a ono to samo fungovalo. Představoval bych si to nějak takhle:
class UsersRepository implements IUsersRepository {
// magic
}
class CustomUsersRepository extends UsersRepository implements IUsersRepository {
public function customMethod(){
// magic
};
}
Napadlo mě přidat to do services a v extension si jen zjistit, jestli už
inmterface IUsersRepository
má nějakou implementaci, pokud ne →
přidat službu UsersRepository. Pokud má implementaci tak nedělat nic.
Pak mě ještě napadlo v extension si vytáhnout všechny implementace interface a pokud existuje nějaká, která dědí tu hlavní, tak ji zaregistrovat, pokud neexistuje tak zaregistrovat tu původní. Tohle se cachuje, takže se to provede jen jednou, že?
Nebo to jde i nějak jinak? Elegantněji?
- Oli
- Člen | 1215
Nemuzji tam dat, protože ten modul mam v composeru a je spolecnej pro všechny projekty. Entity jsem vyřešil traitou, tam to asi jinak nejde. Tady bych vlastně taky mohl, ale pak by aspoň dummy traita musela byt ve všech projektech, to taky nechci. Prave ta traita pro entitu obsahuje další property a v repoditory s tím potřebuju pracovat…
Rozšířit stávající metodu taky není cesta. Bych tam mel zbytečný metody…
- Oli
- Člen | 1215
To prave nemuzu. Celej CMS pracuje s puvodni verzi. Musim pracovat s interface a ten musi mit jen jednu implementaci. Ono to co jsem popsal v tý druhý myšlence by vlastně pro mě bylo good enought, pokud, jak předpokládám, se kompilace extension provede jen jednou a pak se bere z cache…
Ale chtěl jsem jen vědět, jestli není nějaká lepší možnost jak to registrovat jako službu.
- Oli
- Člen | 1215
Ta stará (base, základní, …) se používá všude v základním CMS. Pokud není potřeba nic sciálního, tak je jediná. Pokud je potřeba speciální metoda, tak potřebuju použít jinou třídu, která rozšiřuje tu základní třídu. A ideálem je detekovat, že existuje rozšiřující třída a registrovat ji. Jinak použít základní.
Prostě chci jen vložit třídu a aby to „magicky“ fungovalo.
- Traita v projektu rozšiřuje základní repository: na rozšíření ideální. Bohužel není možný udělat něco jako if trait exists (nebo jo? Takže traita by musela být ve všech projektech.
- Načtení všech tříd, který implementují konkrétní interface. Pokud je jen jedna registrovat jako službu. Pokud jich je víc zjistit jestli je jedna základní a druhá ji rozšiřuje (registrovat tu, která rozšiřuje). Pokud něco jiného vyhodit výjimku…
Ta druhá možnost se mě asi líbí, jak tak nad tím diskutujeme/přemýšlím, asi to je cesta kterou se dát. Má to nějaký nevýhody, zádrhely? Je lepší řešení? Nebo tě vubec nechápu? :-)
- Oli
- Člen | 1215
Má config, ale řeší se tam věci typu název aplikace, email, jazyky, root složka pro obrázky, … Všechny služby si registruje modul, který je za ně zodpovědný tak aby mohl fungovat samostatně.
- tu traitu jsem myslel, že bych vložil do UsersRepository. Do toho rodiče. Šlo by to i naopak. Ale neřeší to to, že musím mít ve všech projektech traitu/třídu.
- CZechBoY
- Člen | 3608
Ta traita ale neřeší nic, ne? Stejně bys musel změnit knihovnu + přidat nějakou traitu, kterou si bude už každej měnit sám (tzn. nebude v knihovně).
Proč vlastně tu metodu potřebuješ mít v tom repozitáři? Nejde si v té třídě využivající daný repozitář vyžádat ještě další třídu, která by měla je tu jednu přídavnou metodu?
- Oli
- Člen | 1215
Ta traita by byla v projektu. A repositar by mel natvrdo
use TUserRepository
. Proto by ta traita musela byt ve vsech
projektech.
Proč vlastně tu metodu potřebuješ mít v tom repozitáři? Nejde si v té třídě využivající daný repozitář vyžádat ještě další třídu, která by měla je tu jednu přídavnou metodu?
Tohle se mě nelíbí, protože mě to zavádí další závislost, která mě přijde zbytečná. A je to víc psaní. Jedinej problém je právě v registraci služby.
Ale teď mě napadlo, nemá být v Nette 2.4 něco jako priorita služeb? Že může být víc implementací interface a já si nastavím, kterou chci využít… Nebo jsem to viděl v nějakým srovnání se Symfony? Už nevím…
- Oli
- Člen | 1215
Tak jsem si s tím trochu hrál a potřeboval bych poradit.
Jakým způsobem zaregistrovat třídu podle interface?
Chtěl bych si načíst všechny třídy, který implementují konkrétní interface a pak se rozhodnout, kterou třídu registrovat. Zkoušel jsem něco jako
foreach (get_declared_classes() as $className) {
if (in_array(IUserRepository::class, class_implements($className))) {
dump( $className);
}
}
Ale v get_declared_classes()
nejsou třídy,
který nejsou jako služby. Pokud zase dám víc služeb se stejným interfacem,
tak to spadne v Nette, že je moc služeb se stejným interface.
Jde tohle nějak vyřešit?