Změna databáze při přihlášení uživatele

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

Zdravím,

chtěl bych Vás požádat o radu/tip na „best practices“ ke změně názvu databáze v aplikaci. Aktuálně je aplikace navržena tak, že používá 2 databázové connections ke dvou různým DBMS (mysql). Jednu pro čtení a druhou pro zápis. Mezi sebou se replikují. Obě mají stejné přístupové údaje ale jiná oprávnění. Jsou to také odlišné stroje.

Obě připojení jsou nastavené v confing.neon.local. DB pro zápis mám jako service a předávám si ji do modelu, který data zapisuje.

Do aplikace se přihlašuje uživatel, který při přihlášení zadává kromě jména a hesla také ID (číslo). To číslo říká, ke které databází v té DBMS pro čtení/zápis se připojí. Všechny databáze na tom stroji mají název XYN, kde to N je zadané číslo při přihlášení. Oproti této databázi se již musí ověřovat přihlašovací údaje.

Neměli by jste radu jak toto nejlépe vyřešit? Napadlo mě několik možností.

  • U každého dotazu určit v dotazu název databáze // SELECT * FROM XY_1.users
  • Při submitnutí formu změnit databázi pomoci USE DATABASE, ale nevím, nakolik je to permanentní
  • V konfigu vytvořit jen connection k DBMS ale DB určit až později. //nevím, zda je to možné

Aplikace bude s toutu vybranou DB pracovat pocelou dobu, až do odhlášení uživatele.

Používám Nette\Database.

Díky za jakékoliv typy a rady

Editoval Onthera (29. 12. 2016 14:23)

Oli
Člen | 1215
+
0
-

To by nemuselo být tak těžké. V configu si definuješ 2 databáze a v service, která se stará o připojení k dtabázi si vybereš. Ta služba by mohla vypadat nějak takhle:

database:
    default:
        dsn: "mysql:host=127.0.0.1;dbname=prvni"
        user: "root"
        password: "password"
        options:
            lazy: true
	druha:
        dsn: "mysql:host=127.0.0.1;dbname=druha"
        user: "root"
        password: "password"
        options:
            lazy: true

services:
	- AuthService(@nette.database.default.context, @nette.database.druha.context)
class AuthService {
	function __construct(Context $database1, Context $database2) {
		$this->database = $database1;
		$this->database2 = $database2;
	}

	public function login($username, $password, $id = null) {
		if (is_null($id) {
			$user = $this->database->table('users')->where('username', $username)->fetch();
		} else if ($id === 2) {
			$user = $this->database2->table('users')->where('username', $username)->fetch();
		}

		// auth magie

		return $user;
	}

}
Onthera
Člen | 5
+
0
-

Oli napsal(a):

Díky za tip, ale tohle nebude to správné řešení. Zapoměl jsem dodat, že počet DB je neznámý. A definovat stovku databází asi nebude úplně ono…

CZechBoY
Člen | 3608
+
-1
-

Já to mám tak, že v konfiguráku mám 200 konfigurací databází a potom pomocí nějaké třídy určím s jakou se teď bude pracovat (id databáze si někam zapersistuj – session, http get, …). Při každém požadavku potom nastavím s jakou databází se bude pracovat.
U tebe je ještě druhej problém a to, že zapisuješ přes jedno spojení a čteš přes druhý. Takže bych si udělal 1 třídu, která mi řekne z jaký databáze mám číst a 2. třídu, která mi řekne do jaký mám zapisovat.

ps. nebo můžeš taky v tom resolveru vytvořit nové spojení a vytvořit Nette\Database\Context atd. sám. Odpadne tak nutnost mít v konfiguráku 200 databází se shodným nastavením připojení a jinou db.

Editoval CZechBoY (29. 12. 2016 14:53)

Oli
Člen | 1215
+
+1
-

@Onthera vycházel jsem z tohohle:

Aktuálně je aplikace navržena tak, že používá 2 databázové connections ke dvou různým DBMS (mysql)

Pokud je počet neznámý, tak si vytvoř nějakou továrnu na connection, které předáš nějakej základ (typ databáze, uživatele, heslo, …) a databázi si vyereš až dynamicky ti přijde ten dotaz. Uměl bych si představit něco jako:

class AuthService {
    function __construct(DatabaseFactory $factory) {
        $this->dbFactory = $factory;
    }

    public function login($username, $password, $id = null) {
		$context = $this->dbFactory->createDatabase($id);

        $user = $context->table('users')->where('username', $username)->fetch();

        // auth magie

        return $user;
    }

}