Připojení k nově vytvořené databázi
- mrudolf
- Člen | 7
Zdravím všechny,
řeším následující problém. V rámci skriptu vytvářím novou databázi a potřebuji získat objekt Context, který by mi umožnil s touto databází dále pracovat.
config.neon
<?php
database:
default:
dsn: "mysql:host=127.0.0.1;dbname=db_zakladni"
user: "dbuzivatel"
password: "dbheslo"
options: [PDO::MYSQL_ATTR_COMPRESS = true]
debugger: true # debugger bar panel
explain: true # explain queries in debugger bar
conventions: discovered # or static or name of your class, default is discovered
autowired: true
#lazy: yes
?>
v BasePresenteru se dostanu ke spojení k základní databázi přes:
<?php
/** @var Nette\Database\Context @inject */
public $dbConnection;
?>
Pomocí $dbConnection vytvořím novou databázi, chtěl jsem poté inicializovat nový Context:
<?php
protected function getNewDBConnection($db_server, $db_name){
$connection = new Nette\Database\Connection("mysql:host=".$db_server.";dbname=".$db_name, ?, ?);
$context = new Nette\Database\Context($connection, ?);
return $context;
}
?>
zde jsem narazil.
- Jak mohu získat údaje z konfiguračního souboru pro Connection (přihlašovací údaje jsou stejné k oběma databázím, kromě jména databáze)
- Při inicializaci Nette\Database\Context je vyžadován druhý parametr IStructure, který není zdokumentovaný na webu. Jaký mám použít?
- CZechBoY
- Člen | 3608
Udělal bych si nějakou ContextFactory, který bych předal jen jméno
databáze a všechno by mi zařídila sama.
nedávno jsem nějakou takovou ukázku psal
https://forum.nette.org/…ez-je-v-neon#…
- mrudolf
- Člen | 7
Uznávám že nejsem v Nette až tak znalý, práce s databází přes Context mi ale vyhovuje. Factory jsem zkopíroval z tvého příspěvku, na to, jak jí propojit s konfiguračním souborem přes službu jsem ale nepřišel.
Uvažuji tedy o přímějším způsobu, v Base presenteru si třídu Connection a Context vytvořit ručně, cca:
<?php
function ($db_number){
$db_config = ? // (získání dat z config.local.neon)
$connection = new Nette\Database\Connection("mysql:host=$db_config['host'];dbname=mojedb_".$db_number, $db_config['user'], $db_config['password']);
$context = new Nette\Database\Context($connection, ?);
return $context;
}
?>
K tomu jsou ale potřeba 2 věci:
- Existuje nějaký snadný způsob, jak se z Presenteru dostat k hodnotám z konfiguračního souboru pro přihlašovací údaje?
řekněme kód v configuračním souboru:
<?php
parameters:
database:
host: "127.0.0.1"
user: "dbuzivatel"
password: "dbheslo"
?>
- způsob vytvoření Contextu jsem našel na https://doc.nette.org/cs/database , kód ale nefunguje:
<?php
new Nette\Database\Context($connection);
?>
Context vyžaduje druhý parametr, kterým je IStructure (Structure). Ta na oplátku potřebuje Nette\Caching\IStorage. Jak tyto mohu na úrovni presenteru získat?
- mrudolf
- Člen | 7
Službu jsem zaregistroval, databázi se mi do ní dostat nepodařilo.
Dohledal jsem nakonec, jak inicializovat nový kontext v Presenteru:
<?php
/**
* @inject
* @var Nette\Caching\IStorage
*/
public $cache;
function dbConn ($db_number){
$db_config = ['host'=>'127.0.0.1', 'user'=>'', 'password'=>''];
$connection = new Nette\Database\Connection("mysql:host=$db_config['host'];dbname=mojedb_".$db_number, $db_config['user'], $db_config['password']);
$structure = new Nette\Database\Structure($connection, $this->cache);
$context = new Nette\Database\Context($connection, $structure);
return $context;
}
?>
Snad se mi ještě podaří dostat parametry spojení z configu…
- CZechBoY
- Člen | 3608
Dej si přihlašovací údaje k databázi jako parametry, který si potom předáš do té ContextFactory (trošku upravíš tu třídu ještě, aby se nedávaly parametry do create metody, ale do konstruktoru).
parameters:
db_user: abc
db_password: abc
db_host: localhost
database:
dsn: "mysql:host=%db_host%;dbname=abc"
user: %db_user%
password: %db_password%
services:
- App\ContextFactory(%db_user%, %db_password%, %db_host%, ...)
use Nette\Database\Connection;
use Nette\Database\Context;
use Nette\Database\IConventions;
use Nette\Database\IStructure;
use Nette\Caching\IStorage;
class ContextFactory
{
private $dbUser;
private $dbPwd;
private $dbHost;
private $structure;
private $conventions;
private $cacheStorage;
public function __construct($dbUser, $dbPwd, $dbHost, IStructure $structure = null, IConventions $conventions = null, IStorage $cacheStorage = null)
{
$this->dbUser = $dbUser;
$this->dbPwd = $dbPwd;
$this->dbHost = $dbHost;
$this->structure = $structure;
$this->conventions = $conventions;
$this->cacheStorage = $cacheStorage;
}
/**
* @return Context
*/
public function create($db, array $options = null)
{
$dsn = 'mysql:host=' . $this->dbHost . ';dbname=' . $db;
$connection = new Connection($dsn, $this->dbUser, $this->dbPwd, $options);
return new Context($connection, $this->structure, $this->conventions, $this->cacheStorage);
}
}
Editoval CZechBoY (27. 9. 2016 18:04)
- mrudolf
- Člen | 7
- Pro manipulaci s jinou DB je potřeba znovu inicializovat Structure a Conventions, jinak si pak Context stěžuje, že tabulky neexistují. Takže jsem v ContextFactory nakonec skončil s:
<?php
public function create($db, array $options = null)
{
$dsn = 'mysql:host=' . $this->dbHost . ';dbname=' . $db;
$connection = new Connection($dsn, $this->dbUser, $this->dbPwd, $options);
$structure = new Structure($connection, $this->cacheStorage);
$conventions = new DiscoveredConventions($structure);
return new Context($connection, $structure, $conventions, $this->cacheStorage);
}
?>
Vše zatím vypadá funkční.