Připojení ke druhé databázi

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

Ahoj, poradíte, jak v configu správně zaregistrovat službu pro připojení k druhé databázi v nette 2.0.4? Docela s tím zápasím.

Zde je můj současný config:

<?php
#
# SECURITY WARNING: it is CRITICAL that this file & directory are NOT accessible directly via a web browser!
#
# If you don't protect this directory from direct web access, anybody will be able to see your passwords.
# https://nette.org/en/security-warning
#
common:
	parameters:
		database:
			driver: mysql
			host: localhost
			dbname: prod1.stormspire.cz
			user: root
			password:

		login_database:
			driver: mysql
			host: localhost
			dbname: login.stormspire.cz
			user: root
			password:

		instance_name: 'martin'
		default_language: 'cs_CZ'
		supported_languages: {'en_GB', 'de_DE', 'cs_CZ', 'sk_SK', 'pl_PL'}
		profiler_log_over: 5
		default_trial_length: 30


	php:
		date.timezone: Europe/Prague
		# session.save_path: "%tempDir%/sessions"
		# zlib.output_compression: yes


	nette:
		session:
			expiration: '+ 14 days'

		database:
			default:
				dsn: '%database.driver%:host=%database.host%;dbname=%database.dbname%'
				user: %database.user%
				password: %database.password%

			login:
				dsn: '%login_database.driver%:host=%login_database.host%;dbname=%login_database.dbname%'
				user: %login_database.user%
				password: %login_database.password%

		debugger:
			email: martin@martinstrouhal.cz


	services:
		database: @nette.database.default
		loginconnection: @nette.database.login
		authenticator: Authenticator( @database::table(ss_users), @database, @userslayer, @user )
		auhorizator: ACL( @database )
		userslayer: AdminModule\UsersLayer( @database )
		roleslayer: AdminModule\RolesLayer( @database )


	factories:


production < common:

development < common:

?>

Zde inject metoda v presenteru:

<?php

	namespace AdminModule;

	// ...

	public function injectUsers(UsersLayer $usersLayer, RolesLayer $rolesLayer, Authenticator $authenticator, \Loginconnection $loginConnection) {
		$this->_usersLayer = $usersLayer;
		$this->_rolesLayer = $rolesLayer;
		$this->_authenticator = $authenticator;
		$this->_loginConnection = $loginConnection;
	}

?>

… a zde chyba. Nevím, zda je chyba v zaregistrování služby, nebo v hintu

<?php
No service of type Loginconnection found. Make sure the type hint in Method AdminModule\UsersPresenter::injectUsers() is written correctly and service of this type is registered. search►
?>

Editoval thunderbuff (26. 8. 2012 13:36)

Filip Procházka
Moderator | 4668
+
0
-

Žádná třída LoginConnection neexistuje, to ti říká ta chyba. Obě dvě připojení jsou instancí Nette\Database\Connection, Nette tedy neumí rozlišit, které je které.

U jednoho tedy budeš muset určit, že je „méně důležité“

services:
	nette.database.login:
		autowired: false

Tyhle dva řádky můžeš úplně vyhodit, jsou tam zbytečné

database: @nette.database.default
loginconnection: @nette.database.login

Zbude ti tedy tohle.

services:
        authenticator: Authenticator(@database::table(ss_users))
        auhorizator: ACL()
        userslayer: AdminModule\UsersLayer()
        roleslayer: AdminModule\RolesLayer()

Nette ti automaticky bude předávat výchozí databázi (a nejenom tu). Teď ale vzniká problém – jak dostat @nette.database.login tam kam potřebuješ. Presenter nakonfigurovat nemůžeš, takže zbývá jediné – obalit ho do služby

class LoginService extends Nette\Object
{
	public function __construct(Nette\Database\Connection $loginDb)
	{
		// ...
	}
}

a tuto si zaregistruješ

services:
        loginService: LoginService(@nette.database.login)

Nyní Nette bude vědět, že tato databáze patří do této třídy a všude jinde bude předávat tu druhou. Zbývá už jen upravit inject metodu.

public function injectUsers(
 UsersLayer $usersLayer,
 RolesLayer $rolesLayer,
 Authenticator $authenticator,
 \LoginService $login)
{
	$this->usersLayer = $usersLayer;
	$this->rolesLayer = $rolesLayer;
	$this->authenticator = $authenticator;
	$this->login = $login;
	// nepoužívej podtržítka, je to škaredé ;)
}

Sice nevím co dělají UsersLayer a RolesLayer, ale možná by nebylo od věci ještě schovat je do LoginService a upravit Authenticator tak, aby tuto LoginService využíval.

A na tebe zbývá poslední úkol, pojmenovat třídu LoginService nějak rozumně, podle toho co doopravdy bude dělat.

Editoval HosipLan (26. 8. 2012 23:27)

thunderbuff
Člen | 164
+
0
-

To je vyčerpávající odpověď, díky! Jen pro úplnost doplním, že UsersLayer a RolesLayer jsou API rozhraní pro správu uživatelských účtů a rolí.

thunderbuff
Člen | 164
+
0
-

Ještě jednou toto téma oživím. Lze nějak udělat dvě připojení k databázi, která budou obě autowirovaná? Napadlo mě jen triviální řešení:

<?php

class SharedConnection extends Nette\Database\Connection {}

// a následné zaregistrování v configu

?>

V té třídě nic víc není, šlo mi jen o to, aby nette bylo schopno rozlišit názvy tříd. Bohužel to nepomohlo a nette stále detekuje dvě služby typu Connection. Lze to nějak vyřešit, nebo musím jedno připojení „obalovat do služby“?

Editoval thunderbuff (16. 9. 2012 19:38)

MKI-Miro
Člen | 277
+
0
-

Ahojte

Ako pripojim dve databzy ponovom ked uz sa neposiela connection ale context ?

Chyba:
must be an instance of Nette\Database\Context, instance of Nette\Database\Connection given

Config:
jos_vm_productRepository: Shop\jos_vm_productRepository(@nette.database.shop)

Metoda:
public function __construct(Nette\Database\Context $db,

Dakujem

MKI-Miro
Člen | 277
+
0
-

Uz som aj nasiel riesenie, ak by niekto potrevoal treba opravit

jos_vm_productRepository: Shop\jos_vm_productRepository(@nette.database.shop)

na

jos_vm_productRepository: Shop\jos_vm_productRepository(Nette\Database\Context(@nette.database.shop))