Problem so ziskanim presenterovej premennej
- figurluk
- Člen | 61
Takto to vyzera na zaciatku mojho presenteru
<?php
private $database,$codeOfCongress,$idOfCongress;
public function __construct(Nette\Database\Context $database)
{
$this->database = $database;
$this->codeOfCongress = "";
$this->idOfCongress = 0;
}
?>
a ak chcem pristupit k premennej $this->codeOfCongress v metode ktora sa
vola po odoslani formularu tak akoby ani neexistovala.. cache vsetko premazane a
refreshnute.
$this->database funguje normalne…
- figurluk
- Člen | 61
<?php
class HomepagePresenter extends BasePresenter
{
private $database,$codeOfCongress,$idOfCongress;
public function __construct(Nette\Database\Context $database)
{
$this->database = $database;
$this->codeOfCongress = "";
$this->idOfCongress = 0;
}
public function renderDefault()
{
if (!$this->getUser()->isLoggedIn()) {
$this->redirect('Sign:in');
}
$this->template->rows = $this->database->table('congres')->select('id,name,code')->order('id');
$this->template->breads = array('Kongresy' => '');
}
public function renderCongres($congresID,$congresCode, $congresName, $actualPage)
{
$this->codeOfCongress = $congresCode;
$this->idOfCongress = $congresID;
$this->template->select_sections = $this->database->table($congresCode.'_sections')->select('id,section');
$this->template->select_hotels = $this->database->table($congresCode.'_hotels')->select('id,hotel');
$numberOfRows = $this->database->table($congresCode.'_participants')->count();
$numberOfPages;
if ($numberOfRows%10 == 0) {
$numberOfPages = $numberOfRows/10;
}
else {
$numberOfPages = (int)($numberOfRows/10)+1;
}
$this->template->countPages = $numberOfPages;
$this->template->actualPage = $actualPage;
$this->template->id = $congresID;
$this->template->code = $congresCode;
$this->template->name = $congresName;
$this->template->rows = $this->database->table($congresCode.'_participants')->order('id')->limit(10,($actualPage-1)*10);
$this->template->breads = array('Kongresy' => 'Homepage:default',$congresName => '');
}
protected function createComponentRegisterForm()
{
$form = new Form;
$form->elementPrototype->addAttributes(array('class' => 'my_form'));
$form->addText("email")->addRule(Form::EMAIL);
...
$form->onSuccess[] = array($this, 'registerFormSucceeded');
return $form;
}
public function registerFormSucceeded($form)
{
$values = $form->getValues(TRUE);
$titul = trim($values['titul'], '.');
$lastVS = NULL;
$lastRow = NULL;
$select = $this->database->table($this->codeOfCongress.'_participants')->select('id,variable_symbol')
->where('variable_symbol IS NOT NULL')
->order('id DESC')->limit(1);
foreach ($select as $symbol)
$lastVS = $symbol->variable_symbol;
if ($lastVS == NULL) {
if ($this->idOfCongress < 10) {
$lastVS = '150'.$this->idOfCongress.'001';
}
else{
$lastVS = '15'.$this->idOfCongress.'001';
}
} else {
$lastVS++;
}
if ($values['typUbytovania'] != 0) {
} else {
}
if($values['aktivnaUcast']) {
}
$this->flashMessage("Uloženie účastníka prebehlo v poriadku.", 'success');
}
}
?>
Editoval figurluk (26. 5. 2015 22:47)
- David Matějka
- Moderator | 6445
render metody se volaji pred po zpracovani formu, viz zivotni
cyklus (form se zpracovava na urovni handle*), takze pouzij action metodu
(alespon pro naplneni tech tridnich properties)
- figurluk
- Člen | 61
David Matějka napsal(a):
render metody se volaji pred zpracovanim formu, viz zivotni cyklus (form se zpracovava na urovni handle*), takze pouzij action metodu (alespon pro naplneni tech tridnich properties)
No ved to je dobre ze sa volaju pred zpracovanim formu… tym padom by tam ta
premenna mala byt ne ?
Ako je mozne ze database tam je a funguje ale tie zvysne 2 nefunguju…
Editoval figurluk (26. 5. 2015 22:59)
- David Matějka
- Moderator | 6445
@figurluk typo :) render metody se volaji po zpracovani formu
tudiz po odeslani dojde ke zpracovani a az pote by se zavolala ta render metoda, kde naplnujes ty properties
Editoval David Matějka (26. 5. 2015 23:03)
- David Matějka
- Moderator | 6445
tady jde pouze o zivotni cyklus presenteru v ramci jednoho requestu – nejdriv se zavola metoda actionCongres (kterou nemas, ale musis ji vytvorit) – v ni prave naplnis ty tridni properties, potom se zavola zpracovani a potom renderCongres
- figurluk
- Člen | 61
David Matějka napsal(a):
tady jde pouze o zivotni cyklus presenteru v ramci jednoho requestu – nejdriv se zavola metoda actionCongres (kterou nemas, ale musis ji vytvorit) – v ni prave naplnis ty tridni properties, potom se zavola zpracovani a potom renderCongres
Dakujem !!!
- Blujacker
- Člen | 89
Komponenty nemaji stejny zivotni cyklus jako presentery,
action<>
metody nefunguji. Je spravne tridni properties plnit
v metode attached
?
public function attached($presenter){
parent::attached($presenter);
$this->template->x = $x;
$this->var = $this->model->getVar($presenter->user->id);
}
- Unlink
- Člen | 298
Ano, len $presenter nemusí byť presenter, pretože komponenty môžeš do seba ľubovoľne vnárať
protected function attached($component)
{
parent::attached($component);
if ($component instanceof \Nette\Application\UI\Presenter)
{
//Tuna môžeš
}
}
Poprípade v metode render, záleží od toho, čo potrebuješ
Editoval Unlink (28. 5. 2015 9:50)
- Zax
- Člen | 370
Blujacker napsal(a):
Komponenty nemaji stejny zivotni cyklus jako presentery,
action<>
metody nefunguji. Je spravne tridni properties plnit v metodeattached
?public function attached($presenter){ parent::attached($presenter); $this->template->x = $x; $this->var = $this->model->getVar($presenter->user->id); }
Jak píše Unlink, ano, jde to. Ale doporučuji zvážit, zda by nebylo lepší to obrátit a nechat presenter, aby proměnné předal třeba přes setter, protože jinak vytváříš skrytý závislosti.
// v komponentě
public function setFoo($foo) {
$this->foo = $foo;
return $this; // fluent
}
// v presenteru
function createComponentAbc() {
return $this->abcFactory->create()
->setFoo($this->getFoo());
}
A pokud nepotřebuješ nic vyloženě z presenteru, ale jen třeba z usera nebo jiný služby, tak si tu službu prostě vyžádej v konstruktoru komponenty a nemusíš vůbec „čekat“ na presenter.

- Blujacker
- Člen | 89
Vsak ja si danou sluzbu vyzadam v konstruktoru komponenty, ale obcas je
potreba naplnit formular i template nejakymi daty z modelu a bez pretizeni
attached
metody bych to musel volat dvakrat (v render
a createComponent
, resp. v createComponent
kontrolovat
jestli uz je to inicializovany a pokud ne tak zavolat).
Pokud bych si vsechny service predal do presenteru a pak je predaval do komponenty (kterou bych pouzival v nekolika presenterech) tak bych pak pri jedne zmene zavislosti musel menit vsechny presentery takze je lepsi si to predat primo do komponenty, nebo ne? – DI si to sam najde a vsechny zavislosti sam preda bez nutnosti toho aby presenter plnil funkci DI kontejneru.
Pokud to dobre chapu tak kazdy potomek
\Nette\Application\UI\Control
ma pristup na presenter pres
$this->presenter
takze kdyz se chci dostat na usera tak staci
$this->presenter->user...
a nemusim si predavat zavislost na
\Nette\Security\User
– nebo je lepsi reseni nespolehat na
presenter a predat si to?
- Zax
- Člen | 370
Asi nechápu tvůj problém.. jediné místo, kde komponenta není připojená k presenteru, je konstruktor. Opravdu. Rozebereme si to velmi zjednodušeně na jednotlivý kroky:
- Presenteru přijde požadavek – „uživatel odeslal formulář
form
v komponentěcontrol
“ - Presenter zkusí vytáhnout formulář z komponentového stromu –
zavolá
$this->getComponent('control-form')
- To se rozloží na
$this->getComponent('control')->getComponent('form')
- Metoda
getComponent
zjistí, že komponentacontrol
neexistuje a zavolá$this->createComponent('control')
- Tato metoda podle názvu zavolá příslušnou metodu
createComponentControl
- Vytvořená komponenta se připojí k presenteru a až pak ji metoda
getComponent
vrátí - Komponentu
control
máme, je připojená a až teď z ní dolujemeform
–getComponent('form')
→createComponent('form')
→createComponentForm()
Naprosto stejně to funguje i když změníme první krok na:
1. Jsme už v render fázi a chceme vykreslit formulář form
v komponentě control
Tahání Nette služeb (user, session, request) z presenteru asi není „trestné“ a bude ti to fungovat, ale konstruktor je určitě „správnější“ – třída se ke svým závislostem otevřeně hlásí a vyžaduje je, netahá si je pokoutně z nějakého service locatoru (což je vlastně to, na co ten presenter tak trochu degraduješ). Pokud si takto taháš vlastní služby, tak je to určitě mnohem horší, přesně jak píšeš – změníš závislost a jde ti to do kopru, nemůžeš komponentu použít v jiném presenteru. Komponenta slepě věří tomu, že v tom presenteru ta služba/proměnná/getter/cokoliv pod tím konkrétním názvem je a to je přece trochu padlý na hlavu, ne? ;-)
BTW pokud potřebuješ stejný data nasypat jak do formuláře tak do šablony, tak není nic jednoduššího:
private $data;
function getData() {
if($this->data === NULL) {
$this->data = $this->model->getData();
}
return $this->data;
}
function render() {
$this->template->data = $this->getData();
// render
}
function createComponentForm() {
//...
$data = $this->getData();
//...
}
Editoval Zax (29. 5. 2015 3:42)
- Blujacker
- Člen | 89
Svoje vlastni zavislosti komponente predavam pres konstruktor, slo mi prave
o seesion, user, request, ktere jsem tahal z presenteru. Takze best practice
je i tyto zavislosti si predavat pres konstruktor, koukal jsem do Nette
sandboxu a tam to tak opravdu je v komponente. Ale nemelo by se tedy
v presenteru https://github.com/…resenter.php#L34
take predat sluzba \Nette\Security\User
a nepouzivat
presenter->getUser()? Nebo primo v presenteru je toto v poradku?
Jinak se vsim souhlasim, az na ten priklad ktery uvadis, nechtelo se mi psat
do dvou metod (render, createComponent) volani $this->getData()
,
chtel jsem to mit pouze na jednom miste, prislo mi to prehlednejsi mit na jednom
miste, proto jsem dal tu inicializaci do attached
metody.
- Zax
- Člen | 370
Blujacker napsal(a):
Svoje vlastni zavislosti komponente predavam pres konstruktor, slo mi prave o seesion, user, request, ktere jsem tahal z presenteru. Takze best practice je i tyto zavislosti si predavat pres konstruktor, koukal jsem do Nette sandboxu a tam to tak opravdu je v komponente. Ale nemelo by se tedy v presenteru https://github.com/…resenter.php#L34 take predat sluzba
\Nette\Security\User
a nepouzivat presenter->getUser()? Nebo primo v presenteru je toto v poradku?Jinak se vsim souhlasim, az na ten priklad ktery uvadis, nechtelo se mi psat do dvou metod (render, createComponent) volani
$this->getData()
, chtel jsem to mit pouze na jednom miste, prislo mi to prehlednejsi mit na jednom miste, proto jsem dal tu inicializaci doattached
metody.
V presenteru je to ok, z UI\Presenter dědíš, takže není důvod nepoužívat jeho služby, pořád pracuješ s injektnutými službami v rámci jednoho objektu, netaháš si to „odněkud“.
U komponent je to horší v tom, že nemáš jistotu, jaký presenter si
přes $this->presenter
vytáhneš. Jasně – v rámci jednoho
projektu je to asi úplně jedno, ale pak třeba převezmeš nějaký zprasený
projekt, budeš tam chtít přidat tu svou komponentu, protože ti rychle
vyřeší nějaký problém, jenže zjistíš, že to prostě nefunguje –
třeba tam někdo přetížil metodu getSession a zrovna se session pracuješ,
nebo třeba prostě najednou pracuješ s jinou verzí Nette (příkladem budiž
metoda getApplication()
, která je normálně v presenteru
v 2.0.0, v 2.1.0 je deprecated „use dependency injection instead“ a
v 2.2.0 už není vůbec).
S tím attached – já asi uvažuju prostě „obráceně“ :-D Mně přijde lepší mít metodu, kterou získám data, a volat ji a plnit daty co kde potřebuju. Takovej zdroják komponenty pak vypadá třeba takto:
- __construct
- getData
- createComponentForm
- vytvoř form
- naplň form
- render
- naplň šablonu
- vyrenderuj
A je naprosto jasné, co se kde děje, i když se k tomu vrátím za půl roku. Řešit to v attached mi prostě přijde neintuitivní, takový lehce WTF:
- __construct
- createComponentForm
- vytvoř form
- render
- vyrenderuj
- attached
- naplň form
- naplň šablonu
Ale zas jestli ti to vyhovuje to mít takhle na jednom místě, tak asi proč ne.. Ber to tak, že tu jen píšu tipy, co se mně osobně osvědčily, a přeber si to jak chceš ;-) Nechci nikomu nic diktovat, ani říkat že moje cesta je jediná správná, jsem jen takový samouk a dost sólista (zčásti protože jsem asociál :-D a zčásti protože zatím jsem neměl tu čest programovat po boku někoho, kdo si na čistotu a kvalitu kódu potrpí) a určitě toho dělám spoustu špatně… ;-) Ale zase rád poradím, to né že ne, i kdyby blbě, tak mě dyžtak někdo opraví a já budu zas o něco chytřejší :-)