Nette database – Výběr aktuální DB (USE database;)

Upozornění: Tohle vlákno je hodně staré a informace nemusí být platné pro současné Nette.
Lukes
Silver Partner | 68
+
0
-

Zdravím,

potřeboval bych pomoct s následujícím problémem. Mám 3 databáze na jednom MySQL serveru, a rád bych našel nějaký způsob přepnutí databáze. Jako třeba mysql_select_db() v PHP. V předchozích verzích to šlo vyřešit uvedením prefixu před tabulku metodě table(„databáze2.tabulka“) každopádně v 2.0.7 Nette už mi to hlásí, že table(„databáze1.databáze2.tabulka“) neexistuje.

(QLSTATE[42S02]: Base table or view not found: 1146 Table ‚databáze1.databáze2.tabulka‘ doesn't exist)

Neví někdo co s tím ? Je to poměrně běžná věc, čili je mi divné kdyby to nešlo.

Editoval Lukes (27. 12. 2012 2:45)

castamir
Člen | 629
+
0
-

Možná by bylo dobré si udělat nějakou nádstavbu, tzv. model, a v něm volat metody, které provedou konkrétní dotaz z požadované databáze. Údaje k připojení ke všem databázím pak snadno abstrahuješ do configu (DI container) a metody v modelu pak můžeš znovu použít i jinde.

config:

nette:
    database:
        default:
            driver: mysql
            host: localhost
            dbname: database1
            user: john
            password: doe
        test:
            driver: mysql
            host: localhost
            dbname: database2
            user: john
            password: doe


services:
    myModel: MyModel(@database.default, @database.test)

MyModel.php:

class MyModel extends Nette\Object
{
    /** @var Nette\Database\Connection */
    protected $database1;
    /** @var Nette\Database\Connection */
    protected $database2;

    public function __construct(Nette\Database\Connection $db1, Nette\Database\Connection $db2)
    {
        $this->database1 = $db1;
        $this->database2 = $db2;
    }

    public function dotazZprvni()
    {
        return $this->database1->table(...)...;
    }

    public function dotazZdruhe()
    {
        return $this->database2->table(...)...;
    }
}

Určitě to půjde zapsat ještě lépe, ale tohle by tě mohlo přinejmenším nasměrovat…

Editoval castamir (27. 12. 2012 7:06)

Lukes
Silver Partner | 68
+
0
-

Ahoj Díky za reakci, ale potřebuji to právě udělat tak, abych měl pouze jednu instanci třídy Nette\Database\Connection :-/

castamir
Člen | 629
+
0
-

Mohu se zeptat proč?

Lukes
Silver Partner | 68
+
0
-

No mám v tom napsanou aplikaci, a jsou tam hojně používané transakce a nechce se mi to moc přepisovat…

thunderbuff
Člen | 164
+
0
-

A nestačilo by, kdybys do své aplikace pomocí DI dostal správné connection? Pak bys jí nemusel přepisovat vůbec a DI bys využil přesně pro takový případ, pro jaký bylo navrženo.

Config bys měl stejně, jak píše @castamir. Pak bys měl třídu:

<?php

class ConnectionManager extends Nette\Object
{
    /** @var Nette\Database\Connection */
    protected $database1;
    /** @var Nette\Database\Connection */
    protected $database2;

    public function __construct(Nette\Database\Connection $db1, Nette\Database\Connection $db2)
    {
        $this->database1 = $db1;
        $this->database2 = $db2;
    }

    public function getDatabase1() {
    	return $this->database1;
    }

    public function getDatabase2() {
    	return $this->database2;
    }

}

?>

… a tvá aplikace by přijímala správné connection třeba v konstruktoru:

<?php

$app = new MojeAplikace($connMan->getDatabase1());

?>

Editoval thunderbuff (31. 12. 2012 0:46)

enumag
Člen | 2118
+
0
-

@thunderbuff: FUJ!! To co jsi napsal je Service Locator. Jinak tvá myšlenka dát do každého modelu to jedno správné Connection pomocí DI a neonu je samozřejmě správná. Obávám se ale, že daná aplikace pravděpodobně není psaná tímto způsobem a takto jednoduché to zřejmě nebude.

Lukes
Silver Partner | 68
+
0
-

Momentálně to mám takto…

public function getTable1(){
	$this->database->table("databaze1.tabulka1");
}

public function getTable2(){
	$this->database->table("databaze2.tabulka2");
}

A představoval bych si to nějak takto

public function getTable2(){
	// USE databaze2 //
	$this->database->table("tabulka2");
}
enumag
Člen | 2118
+
0
-

@Lukes: Tak to nebude až tak složité. Tomu objektu kde máš uvedené funkce předej obě dvě Connection přes config a pak v té metodě getTable* používej vždy tu správnou db.

thunderbuff
Člen | 164
+
0
-

@enumag: To není service locator v tom „zavrženíhodném“ slova smyslu. Pokud mám v connectionmanageru dvě připojení a obě potřebuji, netahám do aplikace klavír, ale malou krabičku právě na ty dva doutníky. Myslím, že v takovém případě to lze s klidem použít.

// Edit: pokud budou ty připojení jen dvě pevně zadrátovaná v configu, pak ConnectionManager nemá význam, stačí je jen obě injektovat do repository.

Lukes napsal(a):

A představoval bych si to nějak takto

public function getTable2(){
	// USE databaze2 //
	$this->database->table("tabulka2");
}

Při zachování „$this->database->table("tabulka2“);" by šlo „USE DATABASE“ napsat jako setter pro $this->database. Není to vůbec hezké, ale nebudeš muset přepisovat program. Přesto si myslím, že tvé současné řešení je mnohem elegantnější a čístší než to vysněné.

<?php

protected $db1;
protected $db2;

protected function useDatabase1() {
	$this->database = &$this->db1;
}

protected function useDatabase2() {
	$this->database = &$this->db2;
}

?>

Editoval thunderbuff (31. 12. 2012 10:44)