Static vs. non-static method v modelech
- kashpi
- Člen | 48
Snažím se využívat Nette\Database a mám nejnovější beta verzi. Připojení k databázi jsem vyřešil, ale teď řeším jestli to vůbec jde. Do teď mi to šlo jednoduše jen, když jsem data za databáze tahal přímo v presenteru, ale to je potom složitý na správu a je to docela prasácký.
Presenter:
$this->conf = BaseModel::getConfig();
Model:
public static function getConfig() {
return $this->database->table('config')->fetch();
}
jenže ve statické metodě nebere argument $this->
a v non-static to píše
Non-static method BaseModel::getConfig() should not be called
statically, assuming $this from incompatible context
Chtěl jsem to řešit jako když jsem používal dibi, ale pořád se mi to
nedaří
a nerad bych používal modelLoader
- Michal Vyšinský
- Člen | 608
Tady vidím dvě řešení a to ta, že instanci (službu) Nette\Database předáš metodě jako parametr:
public static function getConfig($database) {
return $database->table('config')->fetch();
}
Pak ale u každého použití metody modelu musíš použít ten parametr.
A nebo ještě si udělat statickou property toho modelu a pak volat
self::$database->table…
To bude ale potřeba nějak ošetřit, aby BaseModel::$database bylo
nastaveno.
- Ot@s
- Backer | 476
- Koukni se na quickstart (jak správně napasovat/používat model do/v presenteru, viz. souvislosti kolem DI z config.neon)
- V modelu lze provést to, co chceš – není to ale hygienické
public static function getConfig() {
return Nette\Environment::getApplication()->context->database->table('config')->fetch();
}
Editoval Ot@s (6. 1. 2012 15:20)
- kashpi
- Člen | 48
asi jsem to špatně popsal, takto vypadá celej model
class BaseModel extends \Nette\Object {
/** @var Nette\Database\Connection */
private $database;
public function __construct(Nette\Database\Connection $database) {
$this->database = $database;
}
public function getConfig() {
return $this->database->table('config')->fetch();
}
}
Jde o to, že připojení je OK, ale nevím jak toto dostat do presenteru
edit: Protože když dám
$this->conf = BaseModel::getConfig();
tak mi napíše, že potřebuje statickou metodu
Editoval kashpi (6. 1. 2012 15:26)
- Michal Vyšinský
- Člen | 608
Aha,
tak v tom případě je to jednoduché:
v presenteru:
$model = new BaseModel($this->context->getService("database"));
$model->getConfig();
EDIT: A nebo máš v config.neon registrovaný BaseModel jako službu? V tom případě stačí volat v presenteru:
$this->context->getService("jmenotvesluzby")->getConfig();
Editoval CherryBoss (6. 1. 2012 15:34)
- kashpi
- Člen | 48
Tak to jsem právě doufal, že se tomu vyhnu, ale asi ne. Každopádně díky :)
edit: Ne nemám v configu mám jen
services:
database:
class: Nette\Database\Connection
arguments: ['%database.driver%:host=%database.host%;dbname=%database.dbname%', %database.user%, %database.password%, ..., Nette\Database\Reflection\DiscoveredReflection()]
setup:
- setCacheStorage()
authenticator: Authenticator(@database)
authorizator:
class: Acl
conn:
factory: @database
Editoval kashpi (6. 1. 2012 15:39)
- Michal Vyšinský
- Člen | 608
Tak do service přidej službu basemodel a předej jí jako argument službu
database. Myslím že syntax je takto:
(v sekci services)
basemodel:
class: BaseModel
arguments: %database
A pak v presenteru používáš model tak jak jsem psal
$this->conf = $this->context->getService("basemodel")->getConfig();
Myslím si, že to bude nejčistší řešení. Ale možná někdo ještě poradí lépe. DI není moje silná stránka ;)
- kashpi
- Člen | 48
No to jsem prave moc nechtěl všechno řešit přeš config. Protože čím
víc bude modelu, tak tím víc jich budu muset přidávat do configu (pokud se
nepletu).
Takže to asi udělám tak jak to je nahoře s tím že budu muset vytvořit
novou instanci třídy v každe metodě kterou udělám a nebo to budu postaru
cpat všechno do presentru jako dřív.
$this->database->table('config')->fetch();
- Michal Vyšinský
- Člen | 608
Do presenteru to necpi. Komunikaci z databází má zajišťovat model. Pak by MVP[C] architektura ztrácela význam. Ještě se kdyžtak mrkni na toto
Editoval CherryBoss (6. 1. 2012 15:52)
- kashpi
- Člen | 48
Právě vím, že by to ztratilo význam, ale modelLoderu se chci vyhnout,
protože s ním jsem zápasil už dřív a neúspěšně. Ale je pravda, že to
bylo u nějaké starší verze Nette 2. V téhle nové už by to mohlo jít
líp. Vyzkouším, popřemýšlím co a jak a pak kdyžtak napíšu :)
Je tady toho dost, co bych mohl použí, co jste mi poradili :) jen teď najít
tu, která bude ta správná
- kashpi
- Člen | 48
Tak nakonec jsem využil metodu
$this->baseModel = new BaseModel($this->database);
$this->fooModel = new FooModel($this->database);
s tím, že to v BasePresenteru v metodě startup() tahám do globálních proměnných. Jak jen ten model. A pak už to jen v příslušných metodách používám
$this->template->foo = $this->baseModel->getConfig();
Je doufám, že to není moc prasácký, a že se nebudou zbytečně ty modely tahat (což asi budou) ale že to nebude nijak negativně ovliňovat výkon aplikace
To uvidím až to budu používat dál
Editoval kashpi (6. 1. 2012 17:37)
- bojovyletoun
- Člen | 667
pokud chceš mít ultra-cool-moderní řešení a využít DI v plné síle, podívej se na příklad – presenterfactory pro vytvoření presenteru volá setcontext, a vloží do něj autovwířené argumenty. Takže bude v configu stačit si jen nadefinovat názvy služeb, v přidat property služby do presenteru, přiřadit ji v setcontext, do konstruktoru Base a foomodel určit typ 1 argumentu na Connection( případně Selection)