ako pracovať s modelom, prepojenia s presenterom atd
- account23
- Člen | 36
Ahojte,
nejak blúdim v dokumentácii a návodoch a youtube a všade možne :D ale nemôžem prísť na to ako pracovať s Modelom, ako vlastne funguje, ako ho prepojiť s presenterom a view, čo má byť v model a čo v presenter?
keby bol nejaký príklad nejaký malý web alebo niečo jednoduché vytvorené pomocou modelu, pozeral som QuickStart a tam ani raz model nebol použitý. V dokumentaci blúdim a nemôžem poriadne zistiť ako ho využívať. Na nete je všetko iba na staré verzie, neviem či má význam zisťovať to tam.
Prešiel som z frameworku CodeIgniter a tam model slúžil iba na spájanie sa s databázov, jediné čo som o modele u nette zistil, že to neni tak ako u codeigniter :D
Je vôbec možné naučiť sa pracovať s nette na tejto verzii ?
- vvoody
- Člen | 910
Model nemá žiadnu striktnú formu v nette. Prejdi si príklady, za model sa dá považovať napríklad AlbumRepository.
- romiix.org
- Člen | 343
Vysvetlenie čo je Model: https://doc.nette.org/…n/presenters
https://doc.nette.org/…n/presenters
V skratke: Model zabezpečuje dáta pre Presenter. Obsluhuje dátový zdroj a poskytuje potrebné dáta vo vhodnej forme. Štandardne je model obyčajný objekt definovaný ako služba.
- romiix.org
- Člen | 343
account23 napsal(a):
No pozeram to ale moc tomu nechápem, spýtam sa teda takto.
Spravím nejakú funkciu v modeli, ako ju dostanem do presentera a následne zobrazím na webe ?
To je konkrétna otázka na ktorú sa dá odpovedať:)
Vytvor si model – Napr. triedu TestModel.php
Triedu zaregistruj ako službu. Objekt sa vytvorí iba raz.
Službu dodaj do presentru (princíp Dependency
injection). Buď cez __construct
, metódu inject*
,
setter alebo anotáciu @inject
.
Editoval romiix.org (8. 1. 2014 16:17)
- jiri.pudil
- Nette Blogger | 1032
Jen pro terminologickou úplnost (protože v dokumentaci je to asi příliš nenápadné): model je označení celé vrstvy aplikace, která má na starosti veškerou business logiku a ani ne sebemenším projektu obvykle není reprezentovaná jen jednou třídou.
- iNviNho
- Člen | 352
Podľa mňa je to celé zložité … ja som sa v tom stratil hned, preto som pre pracu s DB začal používať DIBI a moj život je sladší …
V modeli si vytvorim iba funkciu, ktorá mi vráti napr. dané fetchnuté riadky cez return a v presenteri ju volam napr. SelectModel::VyberHracov()
a v modeli mam public static function vyberHracov() {
$select = dibi dotaz …
return $select;
}
Ak ťa to zaujalo, napíšem ti konkrétny príklad …
Editoval iNviNho (8. 1. 2014 18:06)
- Mysteria
- Člen | 797
@account23: Pro Nette DB taky žádnou službu dělat nemusíš, klidně můžeš do presenteru napsat
$model = new \Model\ProductsModel();
$model->findAll();
Ale když to zaregistruješ jako službu, tak pak je to takto:
/**
* @inject
* @var \Model\ProductsModel */
public $model;
$this->model->findAll();
Jednou z výhod služby je, že veškerou její konfiguraci (například dotažení připojení k DB a podobně) neřešíš někde v presenteru ale v config.neon.
Osobně když jsem s Nette začínal, tak jsem taky používal první způsob, protože jsem taky neměl tušení, co to vlastně ta „služba“ je, k čemu to je, jak to vytvořit a podobně, ale časem jsem na to přišel. :)
Jinak co se týká toho MVC problému, tak vlastně to jde úplně zjednodušit, že máš Presenter, který řekne Modelu aby mu dodal data a ty pak dá šabloně, takže úplně jednoduše to není nic víc než:
class TestPresenter {
/**
* @inject
* @var \Model\TestModel */
public $model;
public function renderDefault() {
$this->template->data = $this->model->findAll();
}
}
class TestModel {
/**
* @inject
* @var \Nette\Database\Context */
public $database;
public function findAll() {
return $this->database->table('test')->fetchAll();
}
}
No a v šabloně máš pak proměnnou {$data}, který obsahuje pole všech údajů co máš v DB.
Editoval Mysteria (8. 1. 2014 19:28)
- romiix.org
- Člen | 343
Pred pár dňami sa mi dostal do ruky web ktorý používal všade modely
typu SelectModel::VyberHracov()
– samé statické triedy.
Vyznať sa v takom kóde a dohľadať všetky závisosti je PEKLO!
DI má svoj zmyseľ. Ak sa na to vykašleš len preto, že je to na začiatku trošičku zložitejšie, neskôr to budeš ľutovať. Pravdaže pri malinkom webíku je to jedno, ale ak ti to trochu narastie, buď to potom budeš prepisovať odznovu, alebo budeš trpieť a nadávať si.
- romiix.org
- Člen | 343
To či použiješ
$model = new \Model\ProductsModel(); $model->funkciaModelu();
alebo
\Model\ProductsModel::funkciaModelu()
na veci veľa nemení. Tak či tak používaš model skryte. Na prvý pohľad nie je závislosť na tom modeli zrejmá.
Hlavnou myšlienkou je definovanie závislostí. Tzn. ak ti presenter
závisí na \Model\ProductsModel()
, tak mu radšej dodaj ten objekt
rovno správne nakonfigurovaný tak ako popísal Mysteria v príspevku
vyššie :)
Presenter si objekty ktoré potrebuje k behu navytvára a nezískava od niekiaľ, ale ich hotové dostáva.
- Mysteria
- Člen | 797
@account23: Chápu, že se to může zdát složitý, ale jakmile to tak nějak pochopíš, tak si pak vlastně řekneš že to MVC a DI vlastně je úplně logická a dobrá věc i když zezačátku to nejspíš vidíš jako nějakou složitou a nepochopitelnou věc.
Nejlíp bych to asi vysvětlil na příkladu jo, protože tak to bylo pro mě nejlíp pochopitelný, tak by pro tebe mohlo bejt taky. Vezmi si, že to budeš mít napsaný prasácky:
class ProductsPresenter {
public function renderDefault() {
$this->template->data = (new \Model\ProductsModel())->findAll();
}
}
class ProductsModel{
private $database;
public function __construct() {
$this->database = new \Nette\Database\Context(new \Nette\Database\Connection('mysql:host=localhost;dbname=database', 'root', 'password' ));
}
public function findAll() {
return $this->database->table('test')->fetchAll();
}
}
Jo, ono to takhle fungovat bude. Ale má to několik háčků. První je, co když se rozhodneš změnit připojení k databázi? Všechny modely budeš ručně upravovat? Právě proto by si všechny součásti do toho Modelu měl dávat zvenčí (buď přes ty magické anotace @inject, nebo klidně v konstruktoru), aby prostě bylo jasné co ten Model potřebuje (to jsou ty závislosti). Další věcí je, když se rozhodneš upravit třeba konstruktor toho modelu, tak ve všech prezenterech budeš měnit to vytváření modelu, kdežto když použiješ zase DI, tak v config.neon si tam ten parametr předáš a hotovo. V prezenteru nebudeš muset měnit vůbec nic.
Ono fakt nejlíp to pochopíš v případě, když jedeš prasácky a pak až budeš po páté editovat 10 souborů kvůli jedné změně, tak už si pak možná řekneš, proč jsem jenom nedal tomu DI šanci a neušetřil jsem kupu času. ;)
- account23
- Člen | 36
No pozeral som aj ten článok o DI a tiež tam vkuse točia ohľadom pripojenia k databáze, načo teda slúži config.local.neon ? Nerieši sa to pripojenie na databázu rovno tam a už to viac nikde nemusim riešiť ? Načo by som v každom modely požadoval nové spojenie ?
A čo ak chcem databázu mať zapnutú globálne? Že ju budem využívať v každom scripte a nemusel ju nijak volať, šlo by to ? Alebo na to slúži ten druhý config.neon ?
Ako som už písal, prešiel som z frameworku codeigniter a tam to fungovalo typom – autoload – automaticky mi načítalo model, alebo librari, či helper… na celý script čiže som ho už nemusel nikde viac volať a mohol využívať jeho funkcie. Čiže mohol som naloadovať databázu pre celý script a už som ju nemusel ani raz v celom scripte spomenúť
Editoval account23 (9. 1. 2014 11:23)
- jiri.pudil
- Nette Blogger | 1032
Načo by som v každom modely požadoval nové spojenie ?
Správná otázka. To je nesmysl. Podstatou služby je právě to, že jde v rámci jednoho requestu stále o tutéž instanci. Takže pokud budeš třeba v jednom requestu potřebovat zvýšit hodnocení článku a zároveň přepočítat celkové hodnocení jeho autora a budeš to řešit ve dvou různých třídách, obě ty třídy pracují se stejným připojením.
A čo ak chcem databázu mať zapnutú globálne?
Nerieši sa to pripojenie na databázu rovno tam a už to viac nikde nemusim riešiť ?
Ano, tohle si Nette řeší samo. V neonu uvedeš konfiguraci pro připojení k databázi a Nette z ní vygeneruje patřičnou službu. Není ale pravda, že už to dál nikde nemusíš řešit. Ta služba není globálně dostupná. Proč by to bylo špatně, ses mohl dočíst třeba v dokumentaci nebo výše v příspěvku od @Mysteria.
Takže musíš vyřešit, jak si tu službu zpřístupnit ve vlastní modelové třídě. To se dá jednoduše udělat tak, že si o ni řekneš v konstruktoru. Díky tomu, že pak i tu svoji třídu zaregistruješ v configu jako službu, se Nette samo postará o předání té závislosti.
Potom ti zbývá už jen vyřešit, jak tu svoji službu dostat tam, kde ji potřebuješ. Takže třeba do presenteru. A to Nette opět zajistí samo, když si o tu službu řekneš pomocí @inject anotace nebo inject* metody. (Čistější by opět bylo použít konstruktor, ale vzhledem k tomu, že se z presenterů obvykle vytváří nějaká struktura pomocí dědičnosti, by to mohlo způsobit víc problémů, než usnadnění.)
(edit: o ní → o ni; jejda!)
Editoval jiri.pudil (9. 1. 2014 12:02)
- iNviNho
- Člen | 352
V SelectModel:
<?php
public static function vypisInfoOInzerate($id) {
return dibi::fetch("select * from inzeraty where inzeraty.id_inz = %i", $id);
}
?>
V presenteri
<?php
$info = SelectModel::vypisInfoOInzerate($id);
$this->template->info = $info;
?>
Ja naozaj nevidím v tomto nikde chybu a v modeli nevidím žiadne pripojovanie do DB … Jeden celý rok sme sa na VŠ učili databázy a rád by som si queries rád písal sám, aj keď s použitim NetteDatabase by to šlo jednoduchšie, ale queries sa už robia inak …
- Jan Suchánek
- Člen | 404
iNviNho: Model si předávej do Presenteru přez inject a připojení(dibi) do Modelu v autowiringem v neonu přez konstruktor a nepoužívej singleton.
- Mysteria
- Člen | 797
@account23: Tím, že zaregistruješ v Nette službu neznamená, že ji máš automaticky ve všech modelech a presenterech. Když tu službu potřebuješ, tak ji tam prostě injectneš a tím pádem máš pouze ty služby, které potřebuješ (je nesmysl dávat do všech presenterů úplně všechny služby, když je nepotřebuješ).
@iNviNho: Jak v tvém případě dostáváš dibi do toho modelu? Navíc to používání statických metod, když to není nezbytné, tak podle mě taky není dobrej nápad.
- Mysteria
- Člen | 797
@iNviNho: Co třeba minimálně proto, že Environment je od verze 2.0 deprecated, když pomineme, že tímhle způsobem nejde identifikovat závislost modelu na databázi?
Editoval Mysteria (9. 1. 2014 16:20)
- David Matějka
- Moderator | 6445
@iNviNho: registruj si jeden z extensionu dle tve verze nette https://github.com/…ridges/Nette
- Mysteria
- Člen | 797
@iNviNho: Myslím, že to nemá cenu, je o tom tady celá stránka. Každopádně osobně mě je jedno, že tomu nedáš šanci, nechceš se zlepšit a bráníš špatný přístup. Problém nastává až v případě, kdy je možnost, že se tvýho špatnýho přístupu chytne nováček, kterej nemá možnost poznat, že je to špatně a místo toho, aby se už odzačátku učil správnej postup, tak se naučí něco, co stejně časem vyhodnotí jako „špatnou etapu v programování“ (tam se dostaneš taky, časem).
A nepoužívání zastaralých tříd by snad měla být samozřejmost, tam není co vysvětlovat.
Editoval Mysteria (9. 1. 2014 17:28)
- Pavel Macháň
- Člen | 282
iNviNho napsal(a):
Stále nikto nenapísal, čo sa môže stať a kde je problém.
„identifikovat závislost modelu na databázi?“ je to potrebné? Ak hej, tak už konečne prečo
Píšu to po paměti ± takže tam může být někde chyba.
config.neon – nejsem si teď jistej jestli se do 2.1 dostalo možnost registrovat extension v configu (a jestli jsem to napsal dobře)… kdyžtak zaregistrovat v bootstrapu před vytvořením kontejneru
common:
extensions:
dibi: \DibiNetteExtension
dibi:
driver: mysql
host: localhost
username: test
password: test
database: test_db
lazy: TRUE
index.php
$container = require __DIR__ . '/../app/bootstrap.php';
$container->application->run();
presenter
class HomepagePresenter extends Nette\Application\UI\Presenter {
/**
* @var \DibiConnection
* @injection
*/
public $db;
public function rednerDefault() {
$this->db->query('Select * .....');
}
}
Editoval EIFEL (9. 1. 2014 17:30)
- mystik
- Člen | 312
iNviNho napsal(a):
Stále nikto nenapísal, čo sa môže stať a kde je problém.
„identifikovat závislost modelu na databázi?“ je to potrebné? Ak hej, tak už konečne prečo
Protože skryté závislosti způsobují, že z kódu se ti postupně stane noční můra ;-) Když nevíš jaké závislosti tvoje komponenty mají tak nevíš jaké důsledky může mít změna jedné komponenty na další.
- account23
- Člen | 36
heh docela dobrá diskusia sa tu rozbviedla :) Viete čo by mi naozaj pomohlo ? :) Keby bol niekto tak dobrý a ochotný napísať sem krátky príklad napríklad ako je QuickStart, ale bola by v ňom použitá databáza a nie user z config.neon a aby tento script používal model a bolo to vytvorené bez dibi a úplne korektne ako by sa to malo robiť
Myslím že by to pomohlo veľa ľuďom, čo som pozeral tak tu je taký
návodík:
"":https://pla.nette.org/…tvarime-blog
ale niesom si istý či je to dobré aj na Nette 2.1 a ako by to vypadalo
bez dibi – absolutne som nepochopil ako ho kde dať do akej zložky /libs
či ho obsahuje staršia verzia nette(v 2.1 som zložku libs nenašiel) alebo
myslia libs serveru čo je dosť nanič ak chcem využívať normálny
webhosting
Editoval account23 (9. 1. 2014 18:31)
- Mysteria
- Člen | 797
@account23: Tohle je přesně to, co hledáš s jedinou drobností, že tam je pro DI použito konstruktorů místo @inject anotací. Ale nic ti nebrání jednoduše to upravit na anotace.
/** @var AlbumRepository */
private $albums;
public function __construct(AlbumRepository $albums) {
$this->albums = $albums;
}
/**
* @inject
* @var AlbumRepository */
public $albums;
Úplně stejně u modelu. Obě věci dělají naprosto stejné, správné, druhá je pro „línější“ programátory.
Co se týká libs složky tak to byla výchozí složka pro jakýkoliv knihovny projektu (tzn. Nette, Kdyby, Doctrine2,…). V Nette 2.1 se přejmenovala na vendor.
Editoval Mysteria (9. 1. 2014 18:46)
- David Matějka
- Moderator | 6445
@account23: ano, anotace jsou obcas dulezite pro beh programu, viz https://forum.nette.org/…a-komponentu#…
- Mysteria
- Člen | 797
@account23: Pozor, je rozdíl mezi /* */ a /** */.
/**
* @inject
* @var AlbumRepository */
public $albums;
Tohle je vlastně „příkaz“ pro Nette znějící zhruba takto: „Najdi službu (třídu) AlbumRepository (Repository = Model) a vlož ji do proměnné album.“ Výhodou je, že se všechno udělaná samo, takže vůbec neřešíš, jak se to do tý proměnný uloží, všechno se udělá „samo“.
- account23
- Člen | 36
Ahá takže
/**
* @inject - hľadá model
* @var AlbumRepository - class v modeli a priradí to do premmenéj pod sebou ? :D */
Inač ten priklad na github má takú chybu, chýba tam nejaký ten popis. Skúsil som si to nahodiť no nechápem odkiaľ ten script berie dáta ? :D pridávam tam nejaké dáta a je tam user. Podľa config sa pripájam na localhost test databázi ale tá je prázdna :D Tu je nejaká mágia či čo ? :D
Editoval account23 (9. 1. 2014 19:47)
- David Matějka
- Moderator | 6445
- Mysteria
- Člen | 797
@account23: Ta databáze samozřejmě magická není je to normální SQLite3 databáze (soubor app/model/demo.db3). Ale samozřejmě můžeš si ji exportovat do MySQL, upravit připojení k DB a bude to taky fungovat.
@inject říká, že se má Nette pokusit najít službu (služeb může být víc druhů, ne jenom modely) definovanou ve @var. A ve @var není nic jinýho než název třídy.
Takže když si vytvoříš class MujPrvniModel { }, tak tam bude @var MujPrvniModel a podobně.
Ale vlastně teď jsem si všiml, že tu řešíme @inject služby, ale neřekli jsme ti, jak tu službu vlastně nadefinovat. To se dělá v config.neon:
services:
- Authenticator
- AlbumRepository
Praktické shrnutí:
1. Vytvořit model (a rovnou třeba injectnout databázi, z 99% ji
budeš potřebovat):
class MujModel {
/** @var \Nette\Database\Context */
public $database;
public __construct(\Nette\Database\Context $database) {
$this->database = $database;
}
public function mojeMetoda() {
return null;
}
}
2. Vytvořit službu v config.neon:
services:
- MujModel
3. Vytvořit presenter a injectnout model:
class MujPresenter {
/**
* @inject
* @var MujModel */
public $model;
public function renderDefault() {
$this->template->data = $this->model->mojeMetoda();
}
}
Možná si říkáš, jak to, že u injectu té databáze má ve @var \Nette\Database\Context, když v config.neon není nikde služba - \Nette\Database\Context, ale to je tím, že u databáze to dělá Nette za tebe když ji nakonfiguruješ:
nette:
database:
default:
dsn: 'mysql:host=host;dbname=dbname'
user: user
password: password
reflection: conventional
Samozřejmě tohle je nejzákladnější varianta, služby mohou mít parametry a podobně.
Když se budeš tímhle řídit, tak využíváš jak MVC, tak i DI a tomu kódu není co vytknout. :)
Editoval Mysteria (22. 3. 2014 11:22)
- David Matějka
- Moderator | 6445
@Mysteria: @inject anotace ve sluzbach nepouzivej. krom toho, ze jsou defaultne vypnuty, tak je to osklivy. preferuj konstruktor injection
class MujModel {
/** @var \Nette\Database\Context */
public $database;
public function __construct(\Nette\Database\Context $database)
{
$this->database = $database;
}
public function mojeMetoda() {
return null;
}
}
- Mysteria
- Člen | 797
@account23: V pohodě, rád jsem pomohl. Já to měl horší, jelikož jsem na tohle musel přijít sám.
@matej21: Může se zeptat z jakýho důvodu je pro služby lepší konstruktor před anotacema? Osobně když nepředávám žádné jiné parametry modelu tak preferuju inject, abych tam ten konstruktor nemusel dávat, ale nebránit změnit preference. :)
Ohledně vypnutí, nevím jak v 2.1, ale ve 2.2 jsem nic nezapínal (nebo jsem to zapomněl) a fungují.
- David Matějka
- Moderator | 6445
@Mysteria: v konstruktoru jsou ty zavislosti jasne viditelny a nezpochybnitelny. Kdyz mas zavislosti v properties s @inject anotaci, tak je mozno onen objekt vytvorit bez zavislosti, coz zpusobi, ze bude v nekonzistentnim stavu a nepude s nim pracovat. a kdyz budes mit zavislosti v konstruktoru, neprimo te to nuti psat hezci kod
vice treba https://forum.nette.org/…a-steroidech#…
Editoval matej21 (9. 1. 2014 21:16)
- David Matějka
- Moderator | 6445
@account23: sluzby je vsechno, co mas registrovane v configu pod sekci services (tedy ruzne modelove tridy atd). @inject anotace pouzivej pouze v presenterech. v modelech a jinych sluzbach pouzivej konstruktor injection
Editoval matej21 (9. 1. 2014 22:22)
- Filip Procházka
- Moderator | 4668
Zrada: do configu si můžeš registrovat i presentery a Nette to pozná a bude používat DI Container na jejich vytvoření.
Služba je cokoliv co je registrované v DI Containeru (to se dělá pomocí services v configu).
Ohledně Dependency Injection tady myslím chybí ještě odkaz na tento článek v dokumentaci.
Konstruktor injection je nejčistější možný způsob předání závislostí, protože sám o sobě je součást jazyka. Definuje závislosti nejtvrdším možným způsobem, když si napíšeš třídu
class ArticlesModel extends Nette\Object
{
/** @var Nette\Database\Context @inject */
public $db;
public function getData() {
return $this->db->query('SELECT ...');
}
}
A potom si vytvoříš instanci a zavoláš metodu
$model = new ArticlesModel();
$model->getData();
Tak se model v pohodě vytvoří ale když zavoláš metodu vyskočí na
tebe FATAL ERROR, protože v $db
nic není!
Problém je to v okamžiku kdy mezi vytvořením a použitím máš 100 řádků kódu a ještě je volání metody v podmínce, takže se nemusí provést vždy. Tady se dá snadno přehlédnout chyba a kód může havarovat až na hostingu, kde tvého klienta (nebo tebe) může taková chyba stát peníze.
Když ale naopak definuješ závislost v konstruktoru
class ArticlesModel extends Nette\Object
{
/** @var Nette\Database\Context */
private $db;
public function __construct(Nette\Database\Context $db) {
$this->db = $db;
}
public function getData() {
return $this->db->query('SELECT ...');
}
}
Tak už ani nevytvoříš instanci takového modelu. Víš proč? Protože jazyk jasně říká, nehledě na framework, že třída ke své existenci potřebuje databázové spojení a bez něj nemá smysl aby vznikla její instance.
Tohle to hodí prostě fatal error.
$model = new ArticlesModel();
Proto je konstruktor nejčistší možný způsob předání závislostí. Ohledně těch ostatních více čtení viz už jednou linkovaný post.
- KEnik
- Člen | 10
Zdravím, když jsem se pokusil nastavit dle prispěvku #36
tak mi nette vyhodí chybu:
Nette\DI\ServiceCreationException
Class JidloModel used in service ‚24_JidloModel‘ has not been found or is
not instantiable.
Co mám špatně?
config.neon:
`parameters:
php:
date.timezone: Europe/Prague
# zlib.output_compression: yes
nette:
application:
errorPresenter: Error
mapping:
*: App*Module\Presenters*Presenter
session:
expiration: 14 days
- services
- JidloModel
- App\UserManager
- App\RouterFactory
router: @App\RouterFactory::createRouter `
app/model/JidloModel.php
<?php
namespace App\Model;
class JidloModel extends BaseModel
{
public function get($id)
{
return $this->database->table('jidla')->find($id)->fetch();
}
}
app/model/BaseModel.php
<?php
namespace App\Model;
use Nette\Object;
class BaseModel extends Object
{
public $database;
public function __construct($database)
{
$this->database = $database;
}
}
app/model/presenters/JidloPresenter.php
<?php
namespace App\Presenters;
use Nette,
App\Model;
use JidloGrid;
class JidloPresenter extends DefaultPresenter
{
private $JidloModel;
public function startup()
{
parent::startup();
$this->JidloModel = $this->getModel('JidloModel');
}
- KEnik
- Člen | 10
Update: díky Šamene
config.neon doplnil jsem namespace na:
- services
- App\Model\JidloModel
- Nyní mi to hlásí
Nette\DI\ServiceCreationException
Service ‚22_App_Model_JidloModel‘: Parameter $database in
App\Model\BaseModel::__construct() has no type hint, so its value must be
specified
Editoval KEnik (24. 2. 2014 12:40)
- Šaman
- Člen | 2666
Neví to, co se má předat do konstruktoru jako parametr $database. Musíš
specifikovat jakou třídu to má v systémovém kontejneru najít a předat
(nejspíš Nette\Database\Connection
). Nastuduj si Dependency
Injection v dokumentaci, resp. co je to autowiring
<?php
namespace App\Model;
use Nette\Object;
class BaseModel extends Object
{
public $database;
public function __construct(Nette\Database\Connection $database)
{
$this->database = $database;
}
}
?>
Editoval Šaman (24. 2. 2014 12:59)
- KEnik
- Člen | 10
DIky to už jsme odladil. Měl jsme tam více chyb ze starých pokusu o načtení jinými zpusoby.
ted mám problém použít model v presenteru příklad mi nedává moc smysl
3. Vytvořit presenter a injectnout model:
class MujPresenter {
/**
* @inject
* @var MujModel */
public $model;
public function renderDefault() {
$this->template->data = $this->model->mojeMetoda();
}
}
Jak pozná že má vzít metodu z class MujModel?
presentery maji namespace App\Presenters;
modely namespace App\Model;
toto mi nefunguje:
<?php
namespace App\Presenters;
use Nette,
App\Model;
use JidloGrid;
use App\Model\JidloModel;
class JidloPresenter extends BasePresenter
{
private $jidloModel;
public function renderDefault($id)
{
$this->template->data = $this->jidloModel->mojeMetoda();
}
Výsledek:
Fatal Error
Call to a member function mojeMetoda() on a non-object search►
- Šaman
- Člen | 2666
- To, co se snažíš využívat je autowiring. Podívej se na něj. Využívá typehint a anotace, bez nich to skutečně neví, co použít. Takže je doplň podle té ukázky nahoře.
- Jestli se v posledních commitech nic nezměnilo, tak u anotací
se musí vypsat celý namespace, protože neumí pracovat se sekcí
use
. U typehintů stačí napsat namespace douse
a jako typehint pak použit jen samotný název třídy.
Pokud bys chtěl ukázku odladěného kódu nad aktuálním nette 2.1,
tak na GitHubu mám jednu
miniaplikaci. Jen zrovna to injectování a továrničky nejsou řešené
přímo v presenterech, ale pomocí traity přímo u komponenty/služby,
která se má předat nebo vytvořit (ale je to přesně ten kód, který by se
vložil do presenteru místo řádku use TInjectNeco
, nebo
use TCreateComponentNeco
.)
Radši tě odkážu na jinou ukázku, sice ještě nad vývojovou verzí Nette, ale pro presentery se nic nezměnilo. V tomhle případě si injectuji třídu, kterou později využívám k vytvoření komponenty. Jak anotace @var, tak anotace @inject jsou nutné!
Editoval Šaman (24. 2. 2014 13:20)