Public připojení k databázi pro všechny presentery
- ludek
- Člen | 83
Zdravím, všechny moje presentery potřebují připojení k databázi. V
BasePresenteru
jsem teda napsal
namespace App\Presenters;
abstract class BasePresenter extends Nette\Application\UI\Presenter {
/** @var Nette\Database\Context Pristup k databazi*/
protected $repository; // nebo: public $repository;
public function injectRepository(Nette\Database\Context $database)
{
$this->repository = $database;
}
}
v podřízeném presenteru můžu kdekoliv zavolat
$this->repository->table('tabulka')
:
namespace App\Presenters;
use Nette;
class HomepagePresenter extends BasePresenter {
public function renderDetail($id) {
$product = $this->repository->table('products')->get($id);
$this->template->p = $product;
}
} // class
A pokud nepotřebuju nic složitějšího, nepotřebuju modelovou třídu
ani nic zapisovat do configu, navíc mi to dává jakýsi přehled o tom co
přesně se děje, protože se musí uvádět table()
.
Je v pořádku, že připojení k databázi je v PUBLIC
(nebo
protected
) proměnné? Čtením návodů v dokumentaci a na fóru
jsem nějak pochopil, že se tak porušuje pravidlo zapouzdření a že
teoreticky nevím kde se $this->repository vzalo. Je to ale zcela funkční a
pohodlné – prostě mám databázi kdekoliv, kde dědím od
BasePresenter
. Mohlo by to představovat nějaký skutečný
problém?
EDIT: public proměnná změněna na protected.
Editoval ludek (2. 9. 2016 8:32)
- Oli
- Člen | 1215
Mít to v public proměnné není téměř nikdy úplně správně. To je důvod, proč používám kdyby/autowired.
Každopádně větší problém vidím v tom, že by jsi předával repository přímo do presenteru. Jde o to, že to potom bude velice neznovupoužitelný. Mnohem lepší je, když si uděláš třídu například ProductsRepository a v ní budeš pracovat s tabulkou products. Jde o to, že potom, když budeš dělat další projekt, tak můžeš mít v obou projektech třeba články. Tak jen vezmeš už existující třídu ArticlesRepository a máš napsaný propojení s databází i s vyzkoušenýma/otestovanýma dotazama.
Další krok potom je, dávat i logiku mimo presentery, do komponent. Kdy
máš presenter, kterej si jako jedinou závislost vytáhne
ArticleComponent. ArticleComponent si vytáhne
ArticlesRepository, vytahá z databáze co potřebuje a
zobrazí to. Potom můžeš celej balík s modelem, komponentou + další
související věci vzít a použít dohromady v jiným projektu jen tak, že
si v presenteru zavoláš
protected function createComponentArticle(){...}
a upravíš
šablonu aby zapadala do designu.
- jiri.pudil
- Nette Blogger | 1032
Jelikož používáš inject
metodu, ne @inject
anotaci, můžeš tu property mít klidně protected
, a kdybys to
chtěl mít echt zapouzdřené, tak private
a v potomcích k ní
přistupovat přes getter.
- Jan Suchánek
- Člen | 404
@jiri.pudil: mě se líbí jak je tyhle vlastnosti a metody pěkně schovat do trait viz. Nebo je to špatně?
- jiri.pudil
- Nette Blogger | 1032
@jenicek já sice všechno s výjimkou továren na komponenty předávám v konstruktoru, takže traitou bych si práci spíš přidělal, ale na injecty mi to přijde ok.
- ludek
- Člen | 83
Díky za odpovědi. Prozatím jsem nastavil na protected
a
ještě to uvážím.
Znovupoužitelné to právě je. Zvlášť pro jednoduché dotazování, kde
prostě vím, že v `$this->repository" je přístup k databázi. Naopak se
mi zdá velmi složité psát modelovou třídu pro každou tabulku, když
stejně všechny dělají v podstatě totéž.
- Šaman
- Člen | 2666
Když všechny dělají vpodstatě totéž, tak nemusíš nic psát, jen
podědit. Ale ve chvíli, kdy při práci s články chceš
všechny, které mají nadprůměrné hodnocení
a při práci
s uživateli chceš často jen aktivované
, tak to jsou přesně
metody, které patří do jednotlivých repozitářů.
Úplně nejjednodušší abstraktní repozitář pro mé potřeby je tady,
v BookRepozitory
je i jedna specifická metoda. Samozřejmě to
lze hodně vylepšit, tohle je minimalistický příklad bez magie a anotací
pro školní potřeby.
Jinak traity už nepoužívám, v abstraktních presenterech injectuji nad
public property, v konkrétních chci používat konstruktor (ale taky
používám anotaci, protože jsem líný). Proti kdyby/autowired
mám osobní námitku, že je to magie a zbytečná závislost navíc.
Dnes, s decorator
em bych za akademicky nejčistější
považoval úplné vypnutí podpory inject metod a anotace a používat všude
konstruktor, jen u abstraktních tříd setter injection kterou bych
explicitně nastavil v configu. Ale je to hodně psaní navíc. A úplně
čisté to taky není, protože se i povinné závislosti budou předávat
pomocí setteru, tedy nám nic nezaručí, že se opravdu předají. Stále
zůstává jediné čisté řešení předávání všech povinných
závislostí konstruktorem, ale odměnou takovému puntičkáři budiž
constructor hell
:)
Takže jestli anotaci, inject metody, kdyby, nebo decorator, to závisí jen na osobních preferencích, jaký poměr pracnost/čistota chcete mít. Všechno je to kompromis.