Jak použít jeden objekt pro všechny akce v presenteru?

Upozornění: Tohle vlákno je hodně staré a informace nemusí být platné pro současné Nette.
davez
Člen | 60
+
0
-

Ještě bych se chtěl zeptat na toto… Ve svém projektu pracuji s objektem Osoba. Osoba má v DB ID a jméno. Pro osobu mám osobaRepository, kde mám implementovány metody na práci s DB (vkládání, získávání). osobaRepository mám zaregistrovanou jako službu. V presenterech si osobu podle ID najdu v DB. Teď bych ji chtěl ale nějakým způsobem uložit, abych nemusel v každé action znovu osobu podle ID vyhledávat.

Etch
Člen | 403
+
0
-

Třeba v BasePresenteru

abstract class BasePresenter extends Presenter{
	protected $osoba;

	public function startup(){
		parent::startup();
		$this->osoba = $this->osobaRepository->find($id);
	}
}

Editoval Etch (17. 7. 2013 14:43)

davez
Člen | 60
+
0
-

Etch napsal(a):

Třeba v BasePresenteru

abstract class BasePresenter extends Presenter{
	protected $osoba;

	public function startup(){
		parent::startup();
		$this->osoba = $this->osobaRepository->find($id);
	}
}

Jasně díky :). Ještě jedna věc – Když provedu toto:

$this->osoba = $this->osobaRepository->searchOsobaById($id);

tak mi to vrátí pole těch osob, ale vždy tam bude jen jedna. Mohu k té jediné osobě pak přistupovat takto:

$this->osoba[0] ;

?

Michal Vyšinský
Člen | 608
+
0
-

Však v metodě searchOsobaById máš vždy jen jednu osobu ne? Takže vracej rovnou tu jednu osobu.

frosty22
Člen | 373
+
0
-

Přesně jak píše CherryBoss, podle názvu metody „searchOsobaById“ se očekává, že bude vrácena pouze jedna osoba nikoliv pole (*Id = identifikátor), tudíž máš problém v tvém repozitáři.

Což mimochodem ti nikdo neporadí, když nevidíme implementaci tvého objektu osobaRepository – vesměs to může být úplně cokoliv :)

vitush93
Člen | 33
+
0
-

přidej k výběru dat:

...->fetch();
vitush93
Člen | 33
+
0
-

davez napsal(a):

Etch napsal(a):

Třeba v BasePresenteru

abstract class BasePresenter extends Presenter{
	protected $osoba;

	public function startup(){
		parent::startup();
		$this->osoba = $this->osobaRepository->find($id);
	}
}

Jasně díky :). Ještě jedna věc – Když provedu toto:

$this->osoba = $this->osobaRepository->searchOsobaById($id);

tak mi to vrátí pole těch osob, ale vždy tam bude jen jedna. Mohu k té jediné osobě pak přistupovat takto:

$this->osoba[0] ;

?

odpověď na tvojí otázku zní: ano, v tomhle presenteru a v jeho potomcích – za předpokladu, že inicializace té proměnné proběhla před jejím použitím.

Nad všemi action visí metoda startup(), která se spustí nejdříve – tam bych to nejspíš směroval

Editoval vitush93 (17. 7. 2013 17:36)

vitush93
Člen | 33
+
0
-

vitush93 napsal(a):

davez napsal(a):

Etch napsal(a):

Třeba v BasePresenteru

abstract class BasePresenter extends Presenter{
	protected $osoba;

	public function startup(){
		parent::startup();
		$this->osoba = $this->osobaRepository->find($id);
	}
}

Jasně díky :). Ještě jedna věc – Když provedu toto:

$this->osoba = $this->osobaRepository->searchOsobaById($id);

tak mi to vrátí pole těch osob, ale vždy tam bude jen jedna. Mohu k té jediné osobě pak přistupovat takto:

$this->osoba[0] ;

?

odpověď na tvojí otázku zní: ano, v tomhle presenteru a v jeho potomcích – za předpokladu, že inicializace té proměnné proběhla před jejím použitím.

Nad všemi action visí metoda startup(), která se spustí nejdříve – tam bych to nejspíš směroval

nebo dát

$this->osoba = $this->osobaRepository->searchOsobaById($id);

do metody zvlášť a volat si tu metodu v akcích, kde budu potřebovat osobu

frosty22
Člen | 373
+
0
-

Přepokládám, že jsi dělal podle tohoto tutoriálu https://doc.nette.org/cs/quickstart a spíše by mě zajímala tvá implementace repozitáře, kde máš metodu „find“ správně by měla být snad takto (NDB nepoužívám, ale mělo by to tak jít):

<?php
public function find($id) {
  return $this->getTable()->find($id);
}
?>

Odhadl bych, že ty sis ji dopsal jako:

<?php
public function find($id) {
  return $this->getTable()->where(array("id" => $id));
}
?>

což ti vrátí kolekci, potom tedy bys tam musel zavolat ještě fetch(), abys získal první výsledek, ale zároveň tedy musíš se spoléhat na to, že primární klíč má název „id“, což u abstraktního (nějaký baserepository, z něhož dědí ostatní repozitáře) není ideální. Metoda find, což jsem napsal výše, tak ta si zjistí název PK sama a rovnou vrací jeden záznam.

A co se týče té tvé původní otázka, pak pokud to chceš lazy a chceš tahat osobu jen když bude potřeba, pak je elegantnější mít v tom basepresenteru namísto startup způsobu:

<?php
private $osoba;

protected function getOsoba()
{
   if (!isset($this->osoba)) {
   	$this->osoba = $this->osobaRepository->find($id);
   }
   return $this->osoba;
}
?>

A potom ve zděděných presenterech budeš volat tuto metodu namísto přistupování k property.

Šaman
Člen | 2666
+
0
-

Mě se osvědčilo používat v repozitářích:

<?php

// vrátí vždy jeden záznam
$repository->getByEmail($email);

// vrátí vždy pole/kolekci záznamů
$repository->findByColor('black');

// a pro nalezení podle primárního klíče prosté
$repository->get(10);
?>

Pak hned víš, co ti jaká metoda vrací.

Editoval Šaman (18. 7. 2013 6:00)

frosty22
Člen | 373
+
0
-

Ano to je pravda, leč tedy název metody find může být zavádějící, tak ale get rovněž =) Na druhou stranu find je zažitější termín, má ho Doctrine 1, Doctrine 2, NotORM i NDB :) a vždy vrací již jeden záznam nikoliv kolekci. Ale samozřejmě get bych očekával rovněž tak.

Jan Tvrdík
Nette guru | 2595
+
0
-

@frosty22: Z pohledu angličtiny jsou get i find v tomhle ohledu ekvivalentní – ani z jednoho není poznat, zda má vrátit jednu entitu nebo kolekci entit. Konvenci, kterou navrhuje @Šaman, používá Petrovo ORM a nemá žádnou logiku, nicméně pokud je dodržována, tak to v praxi skutečně pomáhá. Jedná se tedy o pragmatickou konvenci.

Alternativní řešení je prodloužit název metod na např. findOneByEmail (může vyhazovat výjimku v případě, že vyhoví více záznamů), findFirstByEmail (jakákoliv entita, která vyhoví) a findAllByEmail (pro kolekce entit). Nebo nějak jinak, možností je tady víc a žádnou nepovažuji za ideální.

Šaman
Člen | 2666
+
0
-

frosty22 napsal(a):

Ano to je pravda, leč tedy název metody find může být zavádějící, tak ale get rovněž =) Na druhou stranu find je zažitější termín, má ho Doctrine 1, Doctrine 2, NotORM i NDB :) a vždy vrací již jeden záznam nikoliv kolekci. Ale samozřejmě get bych očekával rovněž tak.

Doctrine ano, NotORM nevím, ale Ndb používá get a všechno ostatní je jen ukázka v quickstaru, tedy uživatelký kód, nikoliv kód knihovny.

Jinak tu konvenci jsem přebral skutečně z Petrova ORMu a nemám k ní jiný důvod, než že mi vyhovuje. Řešení od @Jan Tvrdík je stejně dobré a jistě by se našly i další. Ale bez nějaké konvence budeš při ladění častěji dumpovat, abys viděl s čím vlastně pracuješ.

frosty22
Člen | 373
+
0
-

Ale bez nějaké konvence budeš při ladění častěji dumpovat, abys viděl s čím vlastně pracuješ.

Tak pokud jsou správně anotace, tak ne :) A tedy předpokládám IDE, doufám že už nikdo nejede v PsPadu :)