Jak v Modelu A volat funkce z Modelu B

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

Zdravím, používam ModelLoader pro načítání modelů a chci se zeptat jak udělat následující.

class ModelA extends BaseModel {
	function foo() {
		$data = ????; // JAK ZAVOLAT FUNKCI ModelB::bar() ?
	}
}

class ModelB extends BaseModel {
	function bar() {
		// TODO
	}
}

Napadlo mě, že bych v ModelLoaderu předával jednotlivým modelům kromě DB připojení ještě instanci ModelLoaderu, ale nevím zda je to to správné ořechové.

Díky za odpověď! .)

Bernard Williams
Člen | 207
+
0
-

Nazdárek,

pokud jej chceš volat staticky, tak jej tak musíš nadefinovat:

public static function bar() {
        // TODO
}

Pak půjde zavolat jako ModelB::bar().

Bernard

Pepino
Člen | 257
+
0
-

Nechci jí volat staticky. Je to tam tak napsáno, ať je jasné, že chci volat funkci bar s třídy ModelB.

Jan Endel
Člen | 1016
+
0
-

ModelLoader osobne nepouzivam, ale podle zdrojaku by melo fungovat klasicky

$this->context->modelLoader->modelB->foo();

ne?

Editoval pilec (31. 7. 2011 14:48)

Pepino
Člen | 257
+
0
-

pilec napsal(a):

ModelLoader osobne nepouzivam, ale podle zdrojaku by melo fungovat klasicky

$this->context->modelLoader->modelB->foo();

ne?

V modelu nejde volat $this->context

Bernard Williams
Člen | 207
+
0
-

A co třeba klasicky:

function foo() {
		$model = New ModelB();
        $data = $model->bar();
}
Jan Endel
Člen | 1016
+
0
-

Pokud pouzivas Tenhle modelLoader tak preci vidim ze v Base modelu se context v konstruktoru normalne plni, cili musi jit volat (pres getContext) a to se dela magii v Nette\Object nebo mi neco unika?

Nebo jak rika Bernard.

Editoval pilec (31. 7. 2011 15:01)

Pepino
Člen | 257
+
0
-

pilec napsal(a):

Pokud pouzivas Tenhle modelLoader tak preci vidim ze v Base modelu se context v konstruktoru normalne plni, cili musi jit volat (pres getContext) a to se dela magii v Nette\Object nebo mi neco unika?

Nebo jak rika Bernard.

Bernard říká nesmysl, jelikož, když udělám $modelB = new ModelB(); tak jak se asi v tom modelu dostanu k připojení k DB.. a připojovat se v každém modelu k db je blbost..

ModelLoader mám vlastní. V podstatě je každý modelLoader skoro stejný.. Ten na který jsi postnul link to řeší právě tak jak jsem napsal, že by to bylo možné.. Akorát místo instance modelLoaderu tam posílá celý container..

Jan Endel
Člen | 1016
+
0
-

Prave a v modelech muzes potrebovat trebas usera, session a dalsi veci, co se resi pres sluzby, tak mi to pres ten context prijde asi nejidealnejsi, pac tim to secko vyresis.

studna
Člen | 181
+
0
-

Obávám se, že nějaký jednoduchý ModelLoader ti tuto věc nevyřeší. Tady je lepší si model sestavit a nějak vložit do ModelLoader::$models a nebo přidat jako obyčejnou službu. Osobně ModelLoader moc nemusím.

Edit: Přes kontejner je to jednoduché, dle mého špatné řešení. ;)

Editoval studna (31. 7. 2011 15:40)

Pepino
Člen | 257
+
0
-

Osobně ModelLoader moc nemusím.

Máš všechny modely registrované jako servis?

Edit: Přes kontext je to jednoduché, dle mého špatné řešení. ;)

Právě proto jsem založil tenhle topic abych našel lepší řešení :)

studna
Člen | 181
+
0
-

Pepino napsal(a):
Máš všechny modely registrované jako servis?

Dá se říct. Ještě předtím, než se aplikace spustí, si zaregistruju téměř všechny služby/modely.

Právě proto jsem založil tenhle topic abych našel lepší řešení :)

Nejlepší řešení je při vytváření instance předat objektu jen tolik služeb/vlastností, které potřebuje ke svému žití. :)

Editoval studna (31. 7. 2011 15:48)

Pepino
Člen | 257
+
0
-

Dá se říct. Ještě předtím, než se aplikace spustí, si zaregistruju téměř všechny služby/modely.

Takže posíláš konstruktoru jednotlivých modelů celý context?

Nox
Člen | 378
+
0
-
  1. předání ať už připojení nebo modelu

Úplně normálně – pomocí DI = ať si to doplní volající… a volající může zas používat nějaký proxy objekt, jako třeba faktory, kde Nette Container je takový mutant mezi Kontejnerem a Factory (ale z nějakýho důvodu se jmenuje jen Container).
Takže se mrknout na možnosti – obecně buď konstruktorem nebo setterem (doporučuje se kontruktor = povinná závislost, setter = volitelná závislost…leda by toho v tom konstruktoru už bylo moc, ale pak by možná sama třída byla moc bloated). A můžeš buď přímo nebo teda v kontejneru
To co píše Bernard skutečně nebrat (tvorba cizí třídy – kde brát její závislosti atd.)

  1. předávání kontejneru

Jestli předávat kontejner nebo konkrétní služby není úplně jasné, na jedné straně je kontejner pohodlný a nemusí být obří konstruktor, na druhé není jasné, co vlastně třída co ho příjmá potřebuje. Imho ani jeden není 100% správný, ale v současnosti předávám Factory třídám kontejner a doménovým třídám už jen konkrétní závislosti…ale říkám, ani jedno není na 100% ok (a to asi nebude nikdy, proto taky naštěstí programujem my a ne cvičené opice), předávání jen potřebného je trochu hezčí

  1. objekty a předávání v PHP

PHP nepracuje s objekty hodnotou, proměnná není ukazatel na jeho data atd. Obsahuje pouze object ID a pokud máš nějaký objekt co umožňuje práci s db a je připojený, pak ho můžeš předat 150ti objektům a stejně se nic nepřipojí víckrát. Objekt je napříč systémem jedinečný, nezdvojí se, pokud nezavoláš třeba manuálně clone


A taky si rozmyslet co vlastně tvoříš. To co je tady na foru nazývané jako Model – „model čeho??“ ⇒ normálně se to jmenuje „Repository“ … pokud potřebuješ u jedné Repository jinou, pak už asi mícháš Repository a Factory dohromady, což taky nebude ideál

Editoval Nox (31. 7. 2011 16:03)

22
Člen | 1478
+
0
-

Podle mě, pokud 2 třídy potřebují společné metody, měl by tyto metody dědit od společného předka. K čemu máš vlastně BaseModel, když tam nemáš definované připojení pro všechny ostatní modely?

Pepino
Člen | 257
+
0
-

Nox napsal(a):

  1. předávání kontejneru

Imho ani jeden není 100% správný, ale v současnosti předávám Factory třídám kontejner a doménovým třídám už jen konkrétní závislosti…

Jestli to dobře chápu tak to co popisuješ je názorně uděláno tady ?

Nox
Člen | 378
+
0
-

O tom mluví i studna, ano, tady se předává konkrétní využívaný objekt (a to že ho třída potřebuje sama sděluje pomocí parametru a jeho typehintu, obvykle je vhodný použít interface místo konkrétní třídy pokud existuje, jednodušeji se pak nahrazuje)

Editoval Nox (31. 7. 2011 16:17)

studna
Člen | 181
+
0
-

Takže posíláš konstruktoru jednotlivých modelů celý context?

Ne, předám jen to, co uvnitř modelu opravdu využiju.

  1. předávání kontejneru

Kontejner je fajn věc, to ano. Pokud potřebuji předávat více služeb pospolu, hodí se. Ale konkrétně u ModelLoaderu mi to nepříjde vhod, nasázet ještě další služby do kontejneru a předávat je všem načítaným modelům.

Pepino
Člen | 257
+
0
-

Nox napsal(a):

obvykle je vhodný použít interface místo konkrétní třídy pokud existuje, jednodušeji se pak nahrazuje)

Pro factories nebo doménové třidy?

Nox
Člen | 378
+
0
-

Pepino tak můžeš všude, googlí se podle „interface driven“ (podmět se různí…programming, architecture, development…) – samozřejmě opět se nemusí aplikovat fanaticky na 100% případů, ale je dobré o interfacech vědět