Jak vytvořit Nette\Database\Context pro více databázi najednou?

crassus
Backer | 78
+
0
-

Ahoj,

jak bych prosím mohl do modelu dostat instanci objektu, pomocí kterého provedu SQL dotaz na více databází zároveň?

Všechny databáze běží na 1 databázovém serveru.

Zároveň bych potřeboval poradit, jakým způsobem dostat do DI kontejneru službu, která mi vrátí Context pouze pro 1 konkrétní databázi, a to na základě vstupního parametru?

Aby modely mohly žádat o Context pro dbname=customer1, tak že vznikne pokaždé jenom 1 instance Contextu s dbname=customer1 pro všechny modely zároveň.

andros
Člen | 145
+
+1
-

Neřešilo se to tady už několikrát ?
Např.: https://forum.nette.org/…dve-databaze

crassus
Backer | 78
+
0
-

andros napsal(a):

Neřešilo se to tady už několikrát ?
Např.: https://forum.nette.org/…dve-databaze

Andros díky za odpověď. Každopádně můj aktuální stav je přesně takový jako v uvedeném vlákně. A nyní bych potřeboval:

  1. Jak udělat 1 SQL dotaz na více databází zároveň.
  2. Aby model dostal instanci Contextu na základě vstupního parametru. Nemůžu dopředu říct, že konkrétní model potřebuje konkrétní Context. Těch Contextu může být N.
h4kuna
Backer | 740
+
+1
-

Platí pro Nette 2.4

Budeš si muset udělat třídu

<?php declare(strict_types=1);

use Nette\Database\Context;
use Nette\DI\Container;

class ContextResolver
{

	/** @var Container */
	private $container;

	public function __construct(Container $container)
	{
		$this->container = $container;
	}


	public function get(string $name): Context
	{
		return $this->container->getService("database.$name.context");
	}

}

Potom ho zaregistrovat v neon, kde máš i databázová spojení

database:
	default:
		dsn: ...
		user: ...
		password: ...

	foo:
		dsn: ...
		user: ...
		password: ...

services:
	- App\Model\ContextResolver

A použiješ ho takto

$contextResolver = $container->getByType(\App\Model\ContextResolver::class);

dumpe($contextResolver->get('default'), $contextResolver->get('foo'));

EDIT:

Pokud potřebuješ spustit jeden dotaz nad více databázemi. Je možnost si všechny Context otagovat a pak je vytáhnout do pole a iterovat na nimi. A nebo si držet seznam názvů spojení a pomocí ContextResolver::get() metody si je vytáhnout. To by bylo dobré znát nějaký use case.

EDIT:
Jak to udělat v Nette 3

Editoval h4kuna (5. 8. 2019 9:29)

crassus
Backer | 78
+
0
-

h4kuna napsal(a):

Platí pro Nette 2.4

Budeš si muset udělat třídu

<?php declare(strict_types=1);

use Nette\Database\Context;
use Nette\DI\Container;

class ContextResolver
{

	/** @var Container */
	private $container;

	public function __construct(Container $container)
	{
		$this->container = $container;
	}


	public function get(string $name): Context
	{
		return $this->container->getService("database.$name.context");
	}

}

Potom ho zaregistrovat v neon, kde máš i databázová spojení

database:
	default:
		dsn: ...
		user: ...
		password: ...

	foo:
		dsn: ...
		user: ...
		password: ...

services:
	- App\Model\ContextResolver

A použiješ ho takto

$contextResolver = $container->getByType(\App\Model\ContextResolver::class);

dumpe($contextResolver->get('default'), $contextResolver->get('foo'));

EDIT:

Pokud potřebuješ spustit jeden dotaz nad více databázemi. Je možnost si všechny Context otagovat a pak je vytáhnout do pole a iterovat na nimi. A nebo si držet seznam názvů spojení a pomocí ContextResolver::get() metody si je vytáhnout. To by bylo dobré znát nějaký use case.

Děkuji mockrát za ukázku toho ContextResolveru.

Je špatně volat v modelech rovnou: $this->container->getService(„database.$name.context“) ? Nebo je lepší na to použít ten ContextResolver?

h4kuna
Backer | 740
+
0
-

Viz post níže.

Editoval h4kuna (30. 12. 2021 7:51)

Marek Bartoš
Nette Blogger | 1274
+
+1
-

Lepší je používat multi locator nebo předávat službu manuálně, řešení ve kterém runtime kód získává službu z containeru podle názvu container degraduje na service locator. Skrývá závislost na službě a při kompilaci containeru se nedozvíte, že služba chybí.

https://forum.nette.org/…azim-zaroven#…