Injektovanie DB to parent modelu
- Čamo
- Člen | 798
No nazdar zase,
Môže mi niekto prosím vysvetliť toto:
Mám triedu BaseModel, ktorá je parentom ostatných tried v modely. Chcel som
do nej injektnuť databázu, ale píše mi to: „Argument 1 passed to
App\Model\BaseModel::__construct() must be an instance of
Nette\Database\Context, none given“
Vyzerá to takto:
class BaseModel
{
/** @var Nette\Database\Context */
public $database;
public function __construct(Nette\Database\Context $db)
{
$this->database = $db;
}
}
a childModel
class UserModel extends BaseModel
{
public function __construct()
{
// create database connection
parent::__construct();
}
...
Ako to mám napísať, aby to fungovalo? Injektovanie funguje len pri inštancovaní, či prečo to nerobí čo chcem?
- Šaman
- Člen | 2665
V potomkovi vůbec konstruktor nepiš. Pokud ho potřebuješ, musíš takto:
<?php
class UserModel extends BaseModel
{
public function __construct(Nette\Database\Context $db, $somethingElse)
{
parent::__construct($db);
# ...
}
}
?>
P.S.
Pokud by $somethingElse nešlo autowirovat (chtěl bys ho předávat v configu
ručně), tak je dobré napsat ho jako první parametr. V configu bys
pak měl:
services:
- NS\UserModel(%somethingElse%) # databáze jako druhý parametr se aurowiruje sama
- NS\UserModel(..., %somethingElse%) # teď bys to musel dělat takhle
Editoval Šaman (6. 8. 2014 22:29)
- Jiří Nápravník
- Člen | 710
BaseModel je podle mě pěkná prasárna. Pokud to používáš jen proto, že jsi líný autowirovat si databázi vždycky, tak to není dle mě dobrý přístup a znásilňuje to dědičnost + si pak zavařuješ na ten problém s konstruktory.
Base třídy jsou vhodné u presenteru (tam je to skoro až nevyhnutelné) a hodí se i u komponent, ale do modelu bych je teda nedával.
- Čamo
- Člen | 798
@Šaman
tým „do nich ale už nic dalšího nepridáva“ myslíš, tých potomkov.
Teda, že nepotrebujú prepisovať konštruktor.
@JiříNápravník
Podľa mňa to má presne ten istý význam ako v presenteroch. To že je
problém s konštruktorom je podľa mňa iná vec.
Asi by to vyriešilo, keby mal BaseModel metódu database()(dá sa injectovať
do metódy?).
Editoval Čamo (7. 8. 2014 12:46)
- Jiří Nápravník
- Člen | 710
Pokud je to Repository, tak by tam nějaká Base třída být mohla, protože tam pak pravděpodobně budou i nějaký metody jako findBy apod.
Nicméně já to pochopil spíše tak, že to je spíše fasádní/servisní třída a tam tedy base třídy nepatří dle mě.
- Čamo
- Člen | 798
A čo injektnúť to do toho BaseModelu cez metódu injectDatabase()?
Našiel som v dokumentácii ako
sa to robí
ale u seba to neviem rozchodiť. Nerozumiem tej syntaxy v NEONe
U mňa Neon vyzerý takto:
services:
- App\RouterFactory
router: @App\RouterFactory::createRouter
- \App\Model\UserModel
- \App\Model\GeneralModel
- \App\Model\BaseModel
inject: yes # nefunguje ani s odsadením píše "expects to be callable or stdClass or null, boolean given"
V dokumentácii je zápis:
services:
service3:
class: App\Service3
inject: yes
čo je úplne iná syntax. Prečo tam ja mám pomlčky a prečo sa v docu tie services pomenovávajú… nechápem.
- David Kudera
- Člen | 455
Pokud má mít služba nějaké další nastavení, tak je potřeba ji pojmenovat a zbytek odsadit pod ni. A nebo třeba takhle bez pojmenování:
services:
-
class: App\Service3
inject: yes
- japlavaren
- Člen | 404
osobne to riesim tak, ze mam ModelDependencies ktory predavam base modelu a potomkom, ktore prepisuju base konstruktor
na @inject hocikde funguje jednoduchy hack
<?php
class XXX
{
public function __construct(DI\Container $container) {
$container->callInjects($this);
}
}
?>
Editoval japlavaren (7. 8. 2014 16:32)
- Čamo
- Člen | 798
Prečo mi nefunguje ten inject?
services:
- App\RouterFactory
router: @App\RouterFactory::createRouter
- \App\Model\UserModel
- \App\Model\GeneralModel
-
class: App\Model\BaseModel
inject: yes
Skúšal som to aj pomenovať, ale stále je $database->table() „on non object“.
class BaseModel
{
/** @var Nette\Database\Context */
public $database;
public function __construct()
{
//$this->database = $db;
}
public function injectDatabase(Nette\Database\Context $db)
{
$this->database = $db;
}
}
Skúšal som všetky možné kombinácie. Nevidí tam niekto nejakú chybu?
Editoval Čamo (8. 8. 2014 10:53)
- David Kudera
- Člen | 455
A kde k tomu $database->table() přistupuješ? zkus si třeba do té inject metody dát dump té databáze, jestli se to v pohodě zavolá. A kdyžtak konstruktor se volá jako první a ne inject, takže jestli máš to volání table v konstruktoru, tak to fungovat určitě nebude
- Šaman
- Člen | 2665
Čamo napsal(a):
Prečo mi nefunguje ten inject?
services: - class: App\Model\BaseModel inject: yes
Takhle to nefunguje! Ty přece nepoužíváš instanci BaseModelu, ale
nějakého konkrétního modelu, dejme tomu UserModelu. A právě teď jsi
kontejneru řekl, ať vytvoří instanci BaseModel a nainjectuje do ní nějaké
závislosti. Ale pak už tuhle instanci nepoužíváš (správně by měla být
ta třída abstraktní, takže nevytvořitelná).
Ty tohle musíš napsat k tomu UserModelu (a ke všem dalším potomkům
BaseModelu)!
Proto je v tomto případě jednodušší řešit to konstruktorem.
Editoval Šaman (8. 8. 2014 11:27)
- David Kudera
- Člen | 455
Šaman napsal(a):
Takhle to nefunguje!
Jéé.. Hlavně že tu radím a vůbec si nevšimnu něčeho takovýho :-D