Jak vytvořit Nette\Database\Context pro více databázi najednou?
- crassus
- Backer | 78
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ň.
- crassus
- Backer | 78
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:
- Jak udělat 1 SQL dotaz na více databází zároveň.
- 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
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
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?
- Marek Bartoš
- Nette Blogger | 1274
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í.