Připojení k více databázím zároveň
- DrakMC
- Člen | 35
Ahoj, potřeboval bych pracovat s více databázemi zároveň. Jak toho docílím? Našel jsem již řešené téma, ale je již 3 roky staré. https://forum.nette.org/…azi-najednou
- nightfish
- Člen | 472
@DrakMC Docílíš toho tak, jak je popsáno ve 3 roky starém vlákně. A nebo třeba dle https://forum.nette.org/…uhe-databazi#…
Zkus popsat, k čemu ta dvě databázová spojení vlastně potřebuješ, možná existuje nějaké jiné řešení tvého problému.
- DrakMC
- Člen | 35
nightfish napsal(a):
@DrakMC Docílíš toho tak, jak je popsáno ve 3 roky starém vlákně. A nebo třeba dle https://forum.nette.org/…uhe-databazi#…
Zkus popsat, k čemu ta dvě databázová spojení vlastně potřebuješ, možná existuje nějaké jiné řešení tvého problému.
Díky za radu. :)
Vyzkoušel jsem to, ale bohužel to nefunguje. Zobrazuje to chybovou hlášku: https://i.imgur.com/cO4Vpkt.png
DatabaseAccessor.php
Mám ho v App\Model – je to dobré umístění? Případně
jaké je lepší?
<?php
namespace App\Model;
interface DatabaseAccessor {
function get($name): \Nette\Database\Context;
}
TestPresenter.php
<?php
namespace App\Presenters;
use App\Model\DatabaseAccessor;
use Nette;
final class TestPresenter extends Nette\Application\UI\Presenter {
/** @var DatabaseAccessor @inject */
public $databaseAccessor;
public function renderDefault(): void {
$db = $this->databaseAccessor->get("db1");
}
}
services.neon
services:
- App\Router\RouterFactory::createRouter
- App\Model\DatabaseAccessor(
db1: @database.db1.context
)
local.neon
parameters:
database:
db1:
dsn: 'mysql:host=127.0.0.1;dbname=databaze'
user: uzivatel
password: heslo
- Marek Bartoš
- Nette Blogger | 1167
On ten interface v Nette 3 vypadá jinak
namespace App\Model;
use Nette\Database\Context;
interface ContextLocator
{
public function getDb1(): Context;
public function getDb2(): Context;
}
services:
- App\Model\ContextLocator(a: @database.db1.context, b: @database.db2.context)
https://github.com/…orMulti.phpt
Editoval Marek Bartoš (30. 12. 2021 1:56)
- Marek Bartoš
- Nette Blogger | 1167
Případně můžeš vyžadovat přímo Context, autowiring mít zapnutý jen pro hlavní databázi a službu s připojením pro další databázi do služeb předávat manuálně
database:
primary:
dsn: 'mysql:host=127.0.0.1;dbname=databaze'
user: uzivatel
password: heslo
backlog:
dsn: 'mysql:host=127.0.0.1;dbname=databaze'
user: uzivatel
password: heslo
autowired: false
services:
- App\Example\Service(@database.backlog.context)
namespace App\Example;
use Nette\Database\Context;
class Service
{
public function __construct(private Context $context)
{
}
}
Editoval Marek Bartoš (30. 12. 2021 1:54)
- DrakMC
- Člen | 35
Marek Bartoš napsal(a):
On ten interface v Nette 3 vypadá jinak
namespace App\Model; use Nette\Database\Context; interface ContextLocator { public function getDb1(): Context; public function getDb2(): Context; }
services: - App\Model\ContextLocator(a: @database.db1.context, b: @database.db2.context)
Díky za rychlou odpověď. Nyní mi to zobrazuje tuto chybovou hlášku: https://i.imgur.com/NI1TuZ9.png
- Marek Bartoš
- Nette Blogger | 1167
Můžeš sem dát celý kód tvého locatoru a jak jej registruješ? Podle testů bych to měl mít imho správně.
Tipnu si: Nette si myslí, že chceš zapsat accessor a ne locator. Accessor
může mít jen jednu metodu nazvanou get()
, ty tam máš
i další. Pojmenuj všechny metody getSomething()
, ne
jen get()
Editoval Marek Bartoš (30. 12. 2021 2:25)
- DrakMC
- Člen | 35
Marek Bartoš napsal(a):
Můžeš sem dát celý kód tvého locatoru a jak jej registruješ? Podle testů bych to měl mít imho správně.
Tipnu si: Nette si myslí, že chceš zapsat accessor a ne locator. Accessor může mít jen jednu metodu nazvanou
get()
, ty tam máš i další. Pojmenuj všechny metodygetSomething()
, ne jenget()
ContextLocator.php
<?php
namespace App\Model;
use Nette\Database\Context;
interface ContextLocator {
public function getDb1(): Context;
}
services.neon
services:
- App\Router\RouterFactory::createRouter
- App\Model\ContextLocator(db1: @database.db1.context)
- DrakMC
- Člen | 35
Ještě přidávám, jak vypadá můj TestPresenter.php:
<?php
namespace App\Presenters;
use App\Model\ContextLocator;
use Nette;
final class TestPresenter extends Nette\Application\UI\Presenter {
/* @var \App\Model\ContextLocator @inject */
public $contextLocator;
public function renderDefault(): void {
$db = $this->contextLocator->getDb1();
}
}
- Marek Bartoš
- Nette Blogger | 1167
Zkus přidat druhou metodu, možná to nepředpokládá, že by byla jen jedna. Jinak to máš imho správně
- DrakMC
- Člen | 35
Bylo to tím – již to funguje. Díky!
Nicméně se mi zobrazil další error: https://i.imgur.com/lXEjvH2.png
Editoval DrakMC (30. 12. 2021 15:57)
- Marek Bartoš
- Nette Blogger | 1167
Nepředává se ti služba. Rozepiš var a inject anotace na více řádků, inline může být jen jedna.
- Marek Bartoš
- Nette Blogger | 1167
/**
* @var \App\Model\ContextLocator
* @inject
*/
public $contextLocator;
Ideálně si ale službu předej v konstruktoru. Mimo base presentery se spoustou závislostí je inject imho zbytečný.
Editoval Marek Bartoš (30. 12. 2021 16:52)
- DrakMC
- Člen | 35
Marek Bartoš napsal(a):
/** * @var \App\Model\ContextLocator * @inject */ public $contextLocator;
Ideálně si ale službu předej v konstruktoru. Mimo base presentery se spoustou závislostí je inject imho zbytečný.
Zobrazil se mi tento error: https://i.imgur.com/81NvmdE.png
Je to tím, že ho nemám přidaný v konstruktoru?
- DrakMC
- Člen | 35
Marek Bartoš napsal(a):
Těžko říct, když nevidím kód
Promiň, zasílám ho. :)
TestPresenter.php
<?php
namespace App\Presenters;
use App\Model\ContextLocator;
use Nette;
final class TestPresenter extends Nette\Application\UI\Presenter {
/**
* @var ContextLocator
* @inject
*/
public $contextLocator;
public function renderDefault(): void {
$db = $this->contextLocator->getDb1();
}
}
ContextLocator.php
<?php
namespace App\Model;
use Nette\Database\Context;
interface ContextLocator {
public function getDb1(): Context;
public function getDb2(): Context;
}
services.neon
services:
- App\Router\RouterFactory::createRouter
- App\Model\ContextLocator(db1: @database.db1.context, db2: @database.db2.context)
- Marek Bartoš
- Nette Blogger | 1167
Zkus sem do LocatorDefinition přidat následující a poslat co ti to vypíše
bdump($name);
bdump($this->references);
Editoval Marek Bartoš (30. 12. 2021 17:29)
- DrakMC
- Člen | 35
Otevřel jsem soubor LocatorDefinition.php ve /vendor/nette/di/src/DI/Definitions a přidal
bdump($name);
bdump($this->references);
Upravený LocatorDefinition.php: https://i.imgur.com/eYJWa7B.png
Domnívám se, že se nic nezměnilo a ukazuje to stejnou chybovou hlášku: https://i.imgur.com/xRTJyXY.png
- Marek Bartoš
- Nette Blogger | 1167
To je správně. Cesta k vygenerovanému kontejneru je vidět v poslední výjimce co jsi posílal. Určitě edituješ správný soubor? Jinde se stejný text výjimky nepoužívá, jestliže se spouští tak by bdump() měl též.
- DrakMC
- Člen | 35
Marek Bartoš napsal(a):
To je správně. Cesta k vygenerovanému kontejneru je vidět v poslední výjimce co jsi posílal. Určitě edituješ správný soubor? Jinde se stejný text výjimky nepoužívá, jestliže se spouští tak by bdump() měl též.
Editoval jsem soubor LocatorDefinition.php v /vendor/nette/di/src/DI/Definitions
Editoval DrakMC (30. 12. 2021 21:01)
- David Grudl
- Nette Core | 8129
@DrakMC měl jsi to od začátku dobře, jen místo
/* @var \App\Model\ContextLocator @inject */
musí být
/** @var \App\Model\ContextLocator @inject */
, ta hvězdička je
podstatná, jinak PHP takový komentář zahodí a Nette se nemá jak
dozvědět, že tam byl.