Výběr databáze – how&best practice
- premek_k
- Člen | 172
Dobrý den, pánové.
Obracím se na vás s velkou prosbou. Nejsem žádný zkušený programátor,
co se PHP týče, dá se říct panic. I přesto jsem na základě materiálů
zde na stránkách a i radách ve fóru dokázal napsat vlastní aplikaci. Je
pravdou, že mi spousta věcí uniká a spoustě věcí nerozumím, ale vždy
jsem se zde dozvěděl, jak vzniklý problém řešit případně i spoustu
informací, jak danou věc udělat lépe, správněji.
Poslední, co mi v tuto chvíli stojí v cestě je myslím hojně využívaný
model aplikace, kdy si uživatel v rámci svého přihlášení vybere i jednu
z připravených databází a nad ní pracuje. Ty databáze jsou strukturou
naprosto shodné a liší se pouze vlastními daty – typicky testovací vs.
provozní databáze. S tímto si stále nevím rady a studium zdejších
materiálů a prolézání fóra nevede k cíli. Návodů a řešení zde
několik je, ale ani jeden z nich není plně použitelný – resp. jsem nic,
od čeho bych se s mými chabými znalostmi odpíchnul, jsem nenašel.
Představa je taková, že použiji NetteDB a že v config.neon budu mít definici spojení s několika MySql databázemi. Po spuštění aplikace je uživateli zobrazen přihlašovací formulář obsahující mimo ostatního i selektbox s výběrem přednastavených databází (vytažených právě z config.neon). V rámci přihlášení uživatele resp. v prvém kroku tohoto procesu si aplikace přebere a nastaví vybrané databázové spojení a dále již nad touto vybranou databází provede ověření uživatele, jeho přihlášení a další práci. Jelikož jsou všechny databáze strukturou shodné, je jedno, kterou databázi si uživatel vybere. Pokud se chce uživatel přepnout do jiné databáze, nejprve se odhlásí z aplikace a následně v přihlašovacím dialogu vybere jiné připojení.
Přesně toto výše popsané chování potřebuji zaimplementovat do své aplikace tak, abych mohl rozšiřovat počet databází jen jejich založením na db serveru a přidáním connectu do config.neon, tzn. bez dalších zásahů do kódu aplikace.
Bohužel po tom, co jsem se zde z různých článků a příspěvků ve fóru dozvěděl, mám stále silnější pocit, že toto nelze v tomto rozsahu v Nette realizovat. Navíc tím, jak se zrovna tato část v Nette vyvíjela, je zde k nalezení spousta již neplatných či zastaralých informací (např. právě způsob zápisů do config.neon), které mne velmi matou a ani zkoušením pokus/omyl se nemohu se hnout z místa.
Proto vás chci poprosit, zda by mne – a nejen mne, všechny ostatní začátečníky s tímto problémem – mohl někdo z vás zkušenějších nasměrovat či nějak poradit, jak uvedené funkčnosti docílit – případně potvrdit mou domněnku, že toto realizovat nelze. Opravdu bych byl velice vděčný za tuto pomoc.
Přemek
- premek_k
- Člen | 172
Aby jste si nemysleli, že tady z vás tahám rozumy a píšu něco, na čem nějak zbohatnu „na váš úkor“, tak můžete kouknout na to o co jde na http://www.geame.cz a aplikace pak „běží“ na http://play.geame.cz
- petr.pavel
- Člen | 535
Doufal jsem, že odpoví někdo, kdo tomu rozumí, protože mě by taky
zajímaly nějaké ty best practices.
Tak ti aspoň napíšu, jak to bastlím já. Založené je to na
volání $databaze->query("USE $nazevDatabaze");
- Jeden db uživatel má přístup ke všem databázím.
- V mém případě se všechny databáze jmenují stejně, až na konec, který znamená rok (sezona_2012, sezona_2013…).
- V config.neon mám připojení k db definováno bez názvu databáze:
nette:
database:
dsn: 'mysql:host=localhost'
- V configu mám taky, jaká je aktuální sezóna – ta se zvolí jako výchozí.
- Všechny objekty, které pracují s db dědí base, která dostává můj
objekt MenicDatabaze, kterému předávám šablonu pro název db
(„sezona_“) a aktuální sezónu („2013“).
Takhle to mám proto, abych parametry v configu musel psát jen jednou a ostatní objekty pak dostanou MenicDatabaze přes autowiring
__construct(NConnection $databaze, MenicDatabaze $menicDatabaze)
services:
menic: MenicDatabaze(%sablonaDb%, %aktualniSezona%)
hriste: HristeModel # ano, v modelu přistupuji k databázi, nekamenujte mě
- MenicDatabaze dostává v konstruktoru i
NConnection $databaze
, které mu předává autowiring.V metodě
zvolSezonu($rok)
pak zkombinuje $this->sablonaDb a$rok
a pomocí$this->databaze->query("USE $nazevDatabaze");
zvolí aktuální databázi.
Cítím, že to není tak úplně to pravé, ale nic lepšího mě nenapadlo.
- castamir
- Člen | 629
Já bych to dělal malinko jinak. Následující text bude spíš nástin, než funkční prototyp.
parameters:
database:
default:
dns: ...
user: ...
default > 2012
dbname: ...
default > 2013
dbname: ...
services:
db: SpravceDb(%database%)
nejakaDbSluzba: NazevSluzby (@SpravceDb)
class SpravceDb {
private $connections = array();
function __construct(array $connection_strings) {
foreach ($connection_strings as $cs) {
$dns = $cs["driver"] . ":" . "host=" . $cs["host"] . ";dbname=" . $cs["dbname"];
// pripadne by mel jit i tento zkraceny zapis
$dns = "{$cs['driver']}:host={$cs['host']};dbname={$cs['dbname']}";
$this->connections[$cs["dbname"]] = new \Nette\Database\Connection($dns, $cs["user"], $cs["password"])
}
}
public function &__get($dbname) {
return $this->connections[$dbname];
}
}
class NazevSluzby {
private $spravceDb;
private $table = "tabulka"; // toto jsem jeste pridal
function __construct(SpravceDb $spravceDb ) {
$this->spravceDb = $spravceDb;
}
public function find($dbname, $key) {
return $this->spravceDb->{$dbname}->table($this->$table)->find($key);
}
}
Kód je zjednodušený a nejspíš tam budou i nějaké chyby, ale princip snad chápete
Edit: pridan atribut $table a upravena metoda na ziskani udaju z parametricky volene databaze.
Edit2: $this->db ⇒ $this->spravceDb
Editoval castamir (1. 3. 2013 14:51)
- petr.pavel
- Člen | 535
@castamir: Buď jsem to nepochopil nebo máš chybu v
public function find($dbname, $key) {
return $this->db->{$dbname}->find($key);
}
Jestli používáš Nette Database nebo NotORM, tak {$dbname}
v tomhle kontextu není název databáze ale tabulky. Takže vlastně databázi
nikde nevolíš.
- premek_k
- Člen | 172
Dobrý den,
děkuji za odpovědi. Výběr databáze pomocí Sql příkazu „USE“ se
nabízel jako nejjednodušší řešení a aplikaci jsem již dříve upravil
tímto způsobem. Bohužel mi čáru přes rozpočet udělal hosting, kdy až
při pokusu to tam dostat jsem s hrůzou zjistil, že nepovolují stejného
usera k více databázím (moc nechápu proč) a každá databáze musí mít
vlastního jednoznačného uživatele. „Grant“ taky nepomohl, mají ho
zakázaný.
No nicméně – jelikož jsem se obával, že na tuto mou prosbu nebude nikdo reagovat – přece jen to není minutová záležitost a osobně si myslím (dle již stávajících témat s touto problematikou), že je zde i obava o „poplivání“ případně zveřejněného kódu, jal jsem se to zkusit řešit úplně od píky a tak, jak na to v tuto chvíli stačí mé znalosti. Výsledkem je následující kód:
Databáze
CREATE DATABASE `prvni`;
CREATE DATABASE `druha`;
CREATE DATABASE `treti`;
USE `prvni`;
CREATE TABLE `pokus` (
`PokusId` int(11) NOT NULL AUTO_INCREMENT,
`PokusText` varchar(50) COLLATE utf8_czech_ci NOT NULL,
PRIMARY KEY (`PokusId`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_czech_ci;
INSERT INTO `pokus` (`PokusId`, `PokusText`) VALUES
(1, 'Databaze Prvni'),
(2, 'Databaze Prvni podruhe');
USE `druha`;
CREATE TABLE `pokus` (
`PokusId` int(11) NOT NULL AUTO_INCREMENT,
`PokusText` varchar(50) COLLATE utf8_czech_ci NOT NULL,
PRIMARY KEY (`PokusId`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_czech_ci;
INSERT INTO `pokus` (`PokusId`, `PokusText`) VALUES
(1, 'Databaze Druha'),
(2, 'Databaze Druha podruhe');
USE `treti`;
CREATE TABLE `pokus` (
`PokusId` int(11) NOT NULL AUTO_INCREMENT,
`PokusText` varchar(50) COLLATE utf8_czech_ci NOT NULL,
PRIMARY KEY (`PokusId`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_czech_ci;
INSERT INTO `pokus` (`PokusId`, `PokusText`) VALUES
(1, 'Databaze Treti'),
(2, 'Databaze Treti podruhe');
CONFIG.NEON
#
common:
parameters:
dbprofiles:
0:
name: 'prvni'
dsn: 'mysql:host=localhost;dbname=prvni'
user: root
password: root
1:
name: 'duha'
dsn: 'mysql:host=localhost;dbname=druha'
user: root
password: root
2:
name: 'treti'
dsn: 'mysql:host=localhost;dbname=treti'
user: root
password: root
php:
date.timezone: Europe/Prague
# zlib.output_compression: yes
nette:
application:
errorPresenter: Error
database:
dsn: 'mysql:host=localhost;dbname=prvni'
user: root
password: root
session:
expiration: 14 days
services:
authenticator: Authenticator
routerFactory: RouterFactory
router: @routerFactory::createRouter
pokusRepository: Sandbox\PokusRepository
factories:
production < common:
development < common:
PokusRepository
<?php
namespace Sandbox;
use Nette;
// ------------------------------------------------------------------
/**
* Tabulka Pokus
*/
class PokusRepository extends Repository
{
// ------------------------------------------------------------------
/**
* Vrat data z tabulky Pokus
*/
public function getPokus() {
return $this->findAll();
}// end function
}//end class
?>
BasePresenter (Jen z důvodu vyzkoušení, zda s tím není problém)
<?php
/**
* Base presenter for all application presenters.
*/
abstract class BasePresenter extends Nette\Application\UI\Presenter
{
// ------------------------------------------------------------------
/**
* pristup k modelu
*/
public $pokusRepository;
// ------------------------------------------------------------------
/**
* Startup
*/
protected function startup()
{
parent::startup();
}//end function
// ------------------------------------------------------------------
/**
* Inject model
*/
public function injectPokusRepository(Sandbox\PokusRepository $PokusRepository)
{
$this->pokusRepository = $PokusRepository;
}//end function
}//end class
?>
No a to hlavní – HomePagePresenter
<?php
use Nette\Application\UI;
use Nette\Application\UI\Form;
// ------------------------------------------------------------------
/**
* Homepage presenter.
*/
class HomepagePresenter extends BasePresenter
{
/** @var \Nette\Database\Connection */
private $database;
// ------------------------------------------------------------------
/**
* konstruktor
*/
public function __construct(Nette\Database\Connection $database)
{
$this->database = $database;
}//end method
// ------------------------------------------------------------------
/**
* Startup
*/
protected function startup()
{
//Nastaveni databaze
$this->setDatabase();
parent::startup();
}//end function
// ------------------------------------------------------------------
/**
* Vytvoreni formulare
*/
protected function createComponentDbSelectForm()
{
$form = new UI\Form;
$form->addSelect('Databaze', 'Databaze:')
->setItems($this->getDatabases());
$form->addSubmit('send', 'Potvrdit');
$form->onSuccess[] = $this->dbSelectFormSucceeded;
return $form;
}//end function
// ------------------------------------------------------------------
/**
* Uspech
*/
private function dbSelectFormSucceeded($form) {
$values = $form->getValues();
//Ulozeni indexu vybrane DB do session
$session = $this->getSession("SelectedDb");
$session->setExpiration(0);
$session->dbIndex = $values->Databaze;
//redirect
$this->redirect("HomePage:Default");
}// end function
// ------------------------------------------------------------------
/**
* Seznam databazi
*/
private function getDatabases() {
$res = array();
$profiles = $this->context->parameters['dbprofiles'];
foreach($profiles as $profile){
array_push($res,$profile["name"]);
}//end foreach
return $res;
}// end function
// ------------------------------------------------------------------
/**
* Nastaveni databaze ze session
*/
private function setDatabase() {
//Vytahnu si ze session index vybrane databaze
$session = $this->getSession("SelectedDb");
$dbIndex = $session->dbIndex;
//Pokud nebylo jeste nastaveno, bude pouzita vychozi databaze
if($dbIndex != null){
//vytahnu info o pripojeni z config.neon
$profile = $this->context->parameters['dbprofiles'][$dbIndex];
$this->database->__construct($profile["dsn"], $profile["user"], $profile["password"]);
}//end if
}// end function
// ------------------------------------------------------------------
/**
* Render stranky
*/
public function renderDefault()
{
$this->template->pokus = $this->pokusRepository->getPokus();
}//end function
}//end class
?>
+ default.latte
{block content}
<h1>Vyber databázi:</h1>
{form dbSelectForm}
{input Databaze}
{input send}
{/form}
<h2>Selekt z tabulky patřičné databáze:</h2>
{foreach $pokus as $p}
<p>{$p->PokusText}</p>
{/foreach}
{/block}
Tímto způsobem to vypadá funkčně, spíš je otázka, jakých nepřístojností jsem se dopustil vůči Nette etice…
Editoval premek_k (1. 3. 2013 13:09)
- castamir
- Člen | 629
Zkusim ti sem sepsat nedostatky:
- duplicitni definice pripojeni k databazi (v parameters a pak nette.database)
- PokusRepository vytvaris jako sluzbu s pripojenim k databazi „prvni“, takze bez ohledu na to, o co se snazis v setDatabase, porad budes pristupovat k databazi „prvni“. A co vic, pokud bys nedejboze zmenil tu databazi z presenteru v PokusRepository, nesmis zapomenou na to, ze se jedna o sluzbu, takze se zmeny promitnou vsude, kde to budes dal pouzivat
- v HomepagePresenteru injektujes databazi, ale pak znasilnujes jeji konstruktor v setDatabase (rozumnej, volas jiz podruhe stejny konstruktor, ktery jiz byl volan, jen s jinymi parametry)
- pouzivas context, ktery je prinejmensim nedoporucovany
- mas vrstvu pro praci s databazi (jednim jeho prvkem je PokusRepository), ale presto si hrajes s databazi jako takovou v presenteru – chyba navrhu
Edit: Takova uzitecna rada pro prehlednejsi a cistejsi kod: Pro metody plati pravidlo „One shot, one kill“, tedy metoda dela jen jedinou vec. Pro objekt plati v podstate to same – mel by se zabyvat v podstate jedinou oblasti, coz v pripade presenteru neni sprava pripojeni k db. Kod, ktery se ridi takovou pouckou se mnohem snad testuje.
Editoval castamir (1. 3. 2013 13:55)
- petr.pavel
- Člen | 535
@castamir: Souhlas. Ohledně tvého předchozího příspěvku:
hlavně ti tam chybí, jak bys v tom __get() měnil tu databázi :-) Jestli
přes $db->query("USE $nazevDatabaze");
nebo jinak.
@premek_k: Tvoje setDatabase() je vlastně továrna na NConnection
(já používám verzi bez prefixů). Mimochodem, nevolal bych
__construct()
ale new NConnection()
, ale čti
dál.
Přijde mi víc Nette definovat to
v configu:
services:
database:
class: Nette\Database\Connection
create: MojeDbTovarna::vytvorPripojeni
arguments: [%dbprofiles%]
vytvorPripojeni
pak bude vlastně tvoje
setDatabase()
. Session tam dostaneš přes auto-wiring (doufám) a
definované databáze přes parametry (psáno z hlavy):
class MojeDbTovarna {
public function vytvorPripojeni($dbprofiles, NSession $session) {
$mojeSession = $session->getSection("SelectedDb");
// jestli nemáš důvod používat zvláštní namespace, tak nemusíš
$dbIndex = $mojeSession->dbIndex;
//Pokud nebylo jeste nastaveno, bude pouzita vychozi databaze
if ($dbIndex === null) {
return null;
}
//vytahnu info o pripojeni z config.neon
$profile = $dbprofiles[$dbIndex];
// tohle jsem vykradl z mého zkompilovaného configu z `createServiceNette__database__default()`
$service = new NConnection($profile["dsn"], $profile["user"],$profile["password"], NULL);
$service->setCacheStorage($this->getService('cacheStorage'));
NDebugger::$blueScreen->addPanel('NDatabasePanel::renderException');
$service->setDatabaseReflection(new NDiscoveredReflection($this->getService('cacheStorage')));
$service->onQuery[] = array(
$this->getService('nette.database.defaultConnectionPanel'),
'logQuery'
);
return $service;
}
}
Editoval petr.pavel (1. 3. 2013 14:40)
- castamir
- Člen | 629
@petr.pavel tak snad poslední úprava mého prvního příspěvku. Dodefinoval jsem to pole $this->connections ve SpravceDb
- premek_k
- Člen | 172
Díky ti za připomínky @castamir, chvíli mi bude trvat, než to pochopím, nicméně narychlo:
- duplicitni definice pripojeni k databazi (v parameters a pak nette.database)
S tímto bych se i smířil. v nette.database je nastavena výchozí databáze, samotný výčet pak v parameters. To že je ta výchozí uvedena v obou sekcích by se dalo ještě ošetřit, ale nepříjde mi to jako zásadní problém.
- PokusRepository vytvaris jako sluzbu s pripojenim k databazi „prvni“, takze bez ohledu na to, o co se snazis v setDatabase, porad budes pristupovat k databazi „prvni“. A co vic, pokud bys nedejboze zmenil tu databazi z presenteru v PokusRepository, nesmis zapomenou na to, ze se jedna o sluzbu, takze se zmeny promitnou vsude, kde to budes dal pouzivat
No nevím. na uvedeném kódu je to funkční – tzn. po výběru databáze se udělá selekt do té správné a vrátí to správná data. Je mi jasné, že to není košér, ale minimálně to funguje.
- v HomepagePresenteru injektujes databazi, ale pak znasilnujes jeji konstruktor v setDatabase (rozumnej, volas jiz podruhe stejny konstruktor, ktery jiz byl volan, jen s jinymi parametry)
Njn, to je proto, že se (krom dalších věcí) neumím vyrovnat s problémem, kdy ve __construct metodě se ještě nedostanu k session a tudíž nemám jak získat index vybrané db (což jsem původně zamýšlel takto udělat). K session se dostanu až ve startup, proto takhle „přes hlavu“.
- pouzivas context, ktery je prinejmensim nedoporucovany
Ano, o tom vím, ale opět – v tuto chvíli se mu neumím ve všech případech vyhnout ($this->context->parameters[‚dbprofiles‘];)
- mas vrstvu pro praci s databazi (jednim jeho prvkem je PokusRepository), ale presto si hrajes s databazi jako takovou v presenteru – chyba navrhu
Moc nerozumím této výtce – o několik řádků výš jsi napsal „…nedejbože změnil tu databázi v PokusRepository…“ a teď zas že bych měl. (???)
Edit: Takova uzitecna rada pro prehlednejsi a cistejsi kod: Pro metody plati pravidlo „One shot, one kill“, tedy metoda dela jen jedinou vec. Pro objekt plati v podstate to same – mel by se zabyvat v podstate jedinou oblasti, coz v pripade presenteru neni sprava pripojeni k db. Kod, ktery se ridi takovou pouckou se mnohem snad testuje.
Jasně, s tím souhlasím a věřím, že mnou zveřejněné řešení není správné v mnoha ohledech. Ale jsem v situaci, kdy nevím jak na to, správné řešení (které bych pochopil) jsem nikde nenašel, moc tomu vlastně ani nerozumím a tak zkouším, jak z toho ven. Království za kus funkčního, správně napsaného a jednoduchého kódu…
Editoval premek_k (1. 3. 2013 15:06)
- castamir
- Člen | 629
@premek_k
Moc nerozumím této výtce – o několik řádků výš jsi napsal „…nedejbože změnil tu databázi v PokusRepository…“ a teď zas že bych měl. (???)
Myslel jsem to tak, ze bys to skarede znovuzavolani konstruktoru pouzil i pro PokusRepository a delegoval to primo do ni. Pokud bys pak nekde volal napriklad nejakou komponentu, jez take pouziva PokusRepository, mohlo by to zpusobit neocekavane chovani. Jak bys pak zjistil, kterou databazi pouzivas v te komponente skrz PokusRepository?
Ano, o tom vím, ale opět – v tuto chvíli se mu neumím ve všech případech vyhnout ($this->context->parameters[‚dbprofiles‘];)
Zastavam nazor, ze bys k parameters nemel pristupovat primo z presenteru, ale v konfigu predhodit konkretni prvek parameters nejake tve tride ci metode.
- premek_k
- Člen | 172
Díky moc, @petr.pavel.
Myšlence rozumím, resp. nevím jen, zda a kde je potřeba
vytvorPripojeni volat, či se již o to nemusím starat a vždy budu
připojen ke správné databázi (ve vlastní režii jen nastavuji dbIndex
v session)???
Facku už jsem si dal…
Editoval premek_k (1. 3. 2013 18:34)
- premek_k
- Člen | 172
Takže aktuální řešení k případnému
připomínkování
Děkuji mnohokrát účastníkům této diskuze za to, že mě nakopli
správným směrem. Výsledné řešení je jakýmsi průnikem…
CONFIG.NEON (Sekce „nette:database:“ zcela ostraněna)
common:
parameters:
dbprofiles:
0:
dbname: 'prvni'
dns: 'mysql:host=127.0.0.1;dbname=prvni'
user: root
password: root
1:
dbname: 'druha'
dns: 'mysql:host=127.0.0.1;dbname=druha'
user: root
password: root
2:
dbname: 'treti'
dns: 'mysql:host=127.0.0.1;dbname=treti'
user: root
password: root
php:
date.timezone: Europe/Prague
# zlib.output_compression: yes
nette:
application:
errorPresenter: Error
session:
autoStart: smart
expiration: +30 days
mailer:
smtp: false
services:
routerFactory: RouterFactory
router: @routerFactory::createRouter
cFactory: Geame\ConnectionFactory(%dbprofiles%)
pokusRepository: Geame\PokusRepository(@cFactory)
factories:
:
:
ConnectionFactory
<?php
namespace Geame;
use Nette;
// ------------------------------------------------------------------
/**
* Pripojeni k databazi
*/
class ConnectionFactory {
private $connection;
private $dbList = array();
function __construct(array $connections, Nette\Http\Session $session, Nette\DI\Container $container) {
// Ze session si vytahnu index databazoveho konektu
$section = $session->getSection("SelectedDb");
$dbIndex = $section->dbIndex;
// Jestlize neni dosud nastaven, nastavuji hlavni databazi (index 0)
if($dbIndex === null){
$dbIndex = 0; //Hlavni databaze
}//end if
// parametry pripojeni spravne databaze
$cs = $connections[$dbIndex];
// vytvoreni a nastaveni konektu
$connection = new \Nette\Database\Connection($cs["dns"], $cs["user"], $cs["password"]);
$connection->setCacheStorage($container->getService('cacheStorage'));
$connection->setDatabaseReflection(new Nette\Database\Reflection\DiscoveredReflection($container->getService('cacheStorage')));
// nastaveni pro blueScreen a DebugBar
Nette\Diagnostics\Debugger::$blueScreen->addPanel('\Nette\Database\Diagnostics\ConnectionPanel::renderException');
$panel = new Nette\Database\Diagnostics\ConnectionPanel;
$panel->explain = TRUE;
$panel->name = 'dbConnectionPanel';
$connection->onQuery[] = array($panel, 'logQuery');
Nette\Diagnostics\Debugger::$bar->addPanel($panel);
// uchovani vytvoreneho konektu
$this->connection = $connection;
//uchovani seznamu dostupnych databazi
foreach($connections as $c){
array_push($this->dbList,$c["dbname"]);
}//end foreach
}//end function
public function &__get($nil) {
return $this->connection;
}//end function
public function getDbList() {
return $this->dbList;
}// end function
}//end class
?>
Repository
<?php
namespace Geame;
use Nette;
abstract class Repository extends Nette\Object
{
private $database;
function __construct(ConnectionFactory $cFactory ) {
$this->database = $cFactory->connection;
}//end function
protected function getTable()
{
// název tabulky odvodíme z názvu třídy
preg_match('#(\w+)Repository$#', get_class($this), $m);
return $this->database->table(strtolower($m[1]));
}//end function
public function findAll()
{
return $this->getTable();
}//end function
}//end class
class PokusRepository extends Repository
{
public function getPokus() {
return $this->findAll();
}// end function
}//end class
?>
HomePagePresenter
<?php
use Nette\Application\UI\Form;
class HomepagePresenter extends BasePresenter
{
private $database;
private $dbList = array();
private $pokusRepository;
function __construct(Geame\ConnectionFactory $cFactory ) {
$this->database = $cFactory->connection;
$this->dbList = $cFactory->getDbList();
}//end function
public function injectPokusRepository(Geame\PokusRepository $PokusRepository)
{
$this->pokusRepository = $PokusRepository;
}//end function
protected function createComponentDbSelectForm()
{
$form = new Form();
$form->addSelect('Databaze', 'Databaze:')
->setItems($this->dbList);
$form->addSubmit('send', 'Potvrdit');
$form->onSuccess[] = $this->dbSelectFormSucceeded;
return $form;
}//end function
public function dbSelectFormSucceeded(Form $form) {
$values = $form->getValues();
//Ulozeni indexu vybrane DB do session
$session = $this->getSession("SelectedDb");
$session->setExpiration(0);
$session->dbIndex = $values->Databaze;
$this->redirect('this');
}// end function
public function renderDefault(){
$this->template->pokus = $this->pokusRepository->getPokus();
}//end function
}//end class
?>
Editoval premek_k (2. 3. 2013 0:42)