Jak na DI v modelu, dědičnost
- bluray
- Člen | 178
Ahoj, chci se zeptat jak používat DI v modelu. Mám například toto:
class AbstractUser{
}
class Admin extends AbstractUser{
}
class User extends AbstractUser{
}
class Guest extends User{
}
Problém je v tom, že aby všechny třídy mohli pracovat s databází,
musí dostat do konstruktoru Context. Nejde to udělat tak, aby Context dostal
pouze AbstractUser? Myslím že DI by to neporušilo. já přece vím, že
třída Admin dědí od AbstractUser a vím, že ten přijímá Context.
Našel jsem tento článek a
tam je ukázána emulace inject property. co si o tom myslíte? je to vhodné
použít? Nechápu proč inject property lze v pohodě používat
u Presenterů ale u modelů tato možnost úplně chybí.
Díky za radu.
- Šaman
- Člen | 2666
Tohle už se tu řešilo.
David má už ve vývojové verzi připravené řešení, musíme si ale počkat
na Nette 2.3.
Do té doby si můžeš buď zapnout injectováni v configu (u všech
potomků), nebo použiješ extension, která je zapne za tebe. Všechny
možnosti by měly být popsané v tom odkazu, včetně kritik daného
řešení.
- trejjam
- Backer | 65
Pokud se jedná jen o přístup k databázi, zachoval bych ji v konstruktoru abstraktní třídy (chybí klíč. slovo abstract). Pokud toho bude víc zapl bych inject:
services:
service3:
class: App\Service3
inject: yes
U modelů chybí proto že zhoršují čitelnost závislostí, v presenterech jsou z důvodu pohodlnosti.
- David Kudera
- Člen | 455
services:
-
class: App\Model\Admin
inject: yes
# když nepotřebuješ inject a další nastavení, tak stačí i jen toto:
- App\Model\Admin
Editoval David Kudera (29. 11. 2014 12:56)
- trejjam
- Backer | 65
v současnosti je nejjednodušší zápis (ve 2.3 by to mělo jít přes extensions (nebo si napsat již nyní svou)):
services:
-
class: \App\Model\Admin
inject: yes
ke konstruktoru:
abstract class AbstractUser {
private $db;
function __construct(...\Context $database) {
$this->db=$database;
}
}
class Admin extends AbstractUser {
function load($id) {
$user=$this->db->table(...)->get($id);
if (!$user) throw new Exception("Pod tímto ID nic není");
return $user;
}
}
- bluray
- Člen | 178
Ještě bych se jednou rád k tomuto tématu vrátil. Mám ted něco takového:
class UserModel{
/**
* @var MySql\UserMySqlStorage
*/
private $database;
/**
* @param \App\Model\MySql\UserMySqlStorage $database
*/
public function __construct(MySql\UserMySqlStorage $database) {
$this->database = $database;
}
}
class AdminModel extends UserModel{
/**
* @var Xml\XmlStorage
*/
private $xml;
public function __construct(Xml\XmlStorage $xml){
$this->xml = $xml;
}
Mám třídy UserMySqlStorage a Xml\XmlStorage registrované jako služby.
A AdminModel je registrován výše popsaným způsobem. Vše funguje do té
doby dokud nepřidám k AdminModel konstruktor s Xml. potom mám v AdminModel
pouze objekt XmlStorage a database je null. Dělám to špatně, nebo to nejde?
Asi budu muset do AdminModelu přidat i ten UserMySqlStorage že?
Díky
- Mysteria
- Člen | 797
Pokud v potomku přepíšeš konstruktor, tak pak musíš volat parent konstruktor…
class AdminModel extends UserModel{
/**
* @var Xml\XmlStorage
*/
private $xml;
public function __construct(MySql\UserMySqlStorage $database, Xml\XmlStorage $xml) {
parent::__construct($database);
$this->xml = $xml;
}