Konfigurace databáze pomocí factory

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

Nějak se neumím dostat přes následující problém. Potřebuji vytvářet Connection pomocí factory, v configu mám něco jako toto:

services:
    database:
        class: Nette\Database\Connection
        factory: DbFactory::createConnection

Problém je, že v té továrně DbFactory::createConnection mám pak natvrdo toto:

$dsn = $container->expand('%database.driver%:host=%database.host%;dbname=%database.dbname%');

Tento zápis bere přímo jednotlivé složky patametru database z configu. Moje aplikace se ale potřebuje připojit k více databázím najednou (a connection je vždy nutné vytvořit přes tuto továrnu) takže potřebuji té továrně nějak předat informaci, který parametr z configu má použít. Jak na to?

Editoval jtousek (29. 6. 2012 22:12)

Filip Procházka
Moderator | 4668
+
0
-

Nepotřebuješ vytvářet connection pomocí factory.

jtousek
Člen | 951
+
0
-

HosipLan napsal(a):

Nepotřebuješ vytvářet connection pomocí factory.

Potřebuju. Ale vysvětlovat proč, by v tvém případě zřejmě byla ztráta času.

Filip Procházka
Moderator | 4668
+
0
-

Vsadím boty že to jde udělat lépe ;)

class ConnectionPool extends Nette\Object
{
	private $connections = array();
	private $configs = array();


	public function __construct($configs)
	{
		$this->configs = $config;
	}

	public function getConnection($name = "default")
	{
		if (!isset($this->connections[$name]) {
			$this->connections[$name] = $this->createConnection($name);
		}

		return $this->connections[$name];
	}

	protected function createConnection($name)
	{
		// if (!isset($this->configs[$name])) throw ...
		$config = $this->configs[$name];
		return new Nette\Database\Connection(
			$config['driver'] . ":host=" . $config['host'] . ";dbname=" . $config['dbname'],
			$config['username'],
			$config['password']
		);
	}

}

nastavím

parameters:
	database:
		default:
			host: ...
			user
		foo:
			...
		bar:
			...

services:
	connectionPoll:
		class: ConnectionPool(%database%)

použvám

$fooConnection = $this->context->connectionPool->getConnection('foo');

Editoval HosipLan (30. 6. 2012 11:10)

jtousek
Člen | 951
+
0
-

Jde to udělat jinak, prostě jsem kód té továrny přesunul do konstruktoru poděděné Connection, zda je to lépe si nejsem úplně jistý.

Zaráží mne ale, že tento příklad je uveden v dokumentaci. Pokud tohle řešení neumožňuje připojení k více databázím najednou tak myslím, že v dokumentaci nemá co dělat.

Editoval jtousek (30. 6. 2012 11:23)

Filip Procházka
Moderator | 4668
+
0
-

Bože… tak to jsme se nepochopili :) ty chceš vytvářet pomocí factory method. Nevíš, proč jsem si v jednu ráno myslel, že chceš použít DIC factories? Promiň :)

Pomocí statické funkce

services:
    database:
        class: Nette\Database\Connection
        factory: DbFactory::createConnection
	arguments:
		- "%database.driver%:host=%database.host%;dbname=%database.dbname%"
		- %database.username%
		- %database.password%

No tak to tam předej všechno, a pak si s tím pracuj jako s polem, tak jak jsem to udělal v tom příkladu

services:
    database:
        class: Nette\Database\Connection
        factory: DbFactory::createConnection(%database%)

Každopádně, Nette nativně podporuje vytváření libovolného množství connections.

Editoval HosipLan (30. 6. 2012 11:16)

jtousek
Člen | 951
+
0
-

Aha, tak to pak jo. :-)

Akorát si nejsem jistej zda tohle bude fungovat… DI Container předává té factory jako první argument sám sebe, takže ta factory pak vypadá takto:

	public static function createConnection(\Nette\DI\Container $container)
	{
		//...
		$service = new \Nette\Database\Connection(...);
		//...
		return $service;
	}

Co by s tím udělalo to factory: DbFactory::createConnection(%database%)? Předalo by se %database% místo toho containeru? Nebo jako druhý parametr? Nebo by to nefungovalo vůbec?

Ono už je to jedno, to řešení přes poděděnou Connection má pro mne ještě jinou výhodu takže to asi stejně nechám tak. :-)

duke
Člen | 650
+
0
-

Řeším podobný problém a mám dotaz. Když chci nahradit Nette\Database\Connection za jinou třídu (vylepšeného potomka), musím parametry k databázi vyhodit ze sekce Nette a dát je přímo pod sekci parameters, abych se na ně pak mohl odkazovat ve své definici služby (např. nette.database.default) v configu? Nebo je pak lepší nette.database úplně obejít a udělat si vlastní databázové služby či rovnou vlastní extension?