Chyba při injekci Nette\Security\User
- David Klouček
- Člen | 57
Mám tu zajímavý problém s tímto modelem:
use Nette\Security as NS;
class UserModel extends Nette\Object implements NS\IAuthenticator
{
/** @var Nette\Database\Context */
protected $db;
/** @var Nette\Security\User */
protected $user;
public function __construct(Nette\Database\Context $db, Nette\Security\User $user)
{
$this->db = $db;
$this->user = $user;
}
}
Aplikaci shodí injekce druhého parametru hláškou „Circular reference detected for services: user, 23_UserModel“. Když ho ale injektuju do modelu, který nemá v názvu „User“ tak bez problému. Netušíte někdo? v2.2RC4, 05–05–14
PS: proč v téhle nové verzi nefunguje @inject v modelu?
Editoval David Klouček (9. 5. 2014 18:56)
- jiri.pudil
- Nette Blogger | 1032
Netušíte někdo?
Viz upozornění v migration guide:
- do
Nette\Security\User
se v konstruktoru předává autentikátor, pozor na kruhové závislosti
proč v téhle nové verzi nefunguje @inject v modelu?
Protože mimo presenter je preferovaný constructor injection. Pokud chceš
injectování přes anotace povolit, musíš to udělat u daných služeb
v konfiguraci (pomocí inject: on
)
- Tomáš Votruba
- Moderator | 1114
Vypadá to, že máš implementaci user/authenticatoru, kam předáváš
model. User → model, model → user a chyba je na světě.
Zkusil bych IAuthenticator
implementovat samostatně, instanci
User
tam nepotřebuješ. Inspiraci můžeš shlédnout v sandboxu
Ad @inject – je od určité verze povolena pouze na presenterech, všude jinde bys měl pro předání závislostí použít konstruktor. Je k tomu pěkný cheat sheet
- David Klouček
- Člen | 57
Tomáš Votruba napsal(a):
Vypadá to, že máš implementaci user/authenticatoru, kam předáváš model. User → model, model → user a chyba je na světě.
Zkusil bychIAuthenticator
implementovat samostatně, instanciUser
tam nepotřebuješ. Inspiraci můžeš shlédnout v sandboxu
Já to mam právě skoro stejně jako v tom sandboxu. Authenticátor v modelu. Logicky mi přijde, že to patří k sobě.. Takže to vlastně musim rozdělit a v modelu si vytvořit metodu, která bude pracovat s authenticatorem? V něm se ale taky musí pracovat s modelem, takže zase Circular reference.
- Jiří Nápravník
- Člen | 710
Máš to právě SKORO stejně.
Jde o to, že ty máš nějaký UserModule, který implementuje rozhraní authenticatoru a v jeho konstruktoru potřebuješ zároveň Nette\Security\User – či-li když ti pak vytváří tvojí DI kontejner objekt UserModel, tak vidí, že potřebuje Nette\Security\User, jenže Nette\Security\User potřebuje zase Authenticator a v tvém případě je Authenticator zase ta třída UserModel a tak neví co má vytvořit jak, protože je v kruhu.
Mělo by ti stačit udělat
UserModel, jako máš, ale smaž z něj to implements NS\IAtuhenticator
vytvoř nvoou třídu, která bude ten Authenticator a ten si pak předej
v konstruktoru (pokud potřebuješ) jako si předáváš NS\User a pracuj
s ním.
- David Klouček
- Člen | 57
Chápu. Ale samotná metoda autenticate v authenticatoru se potřebuje nějak dostat k DB, nejlíp využít ten UserModel a tim se to zas zacyklí. Můžu to vyřešit přímou komunikací s DB ale to se mi moc nelíbí.
- Jiří Nápravník
- Člen | 710
A potřebuješ vůbec tu NS\User v modelové třídě? Já jí tam třeba nemám ani koukám, prostě si přewdávám přímo identitu do metod v modelu, kde potřebuji.
No a když koukám na svůj authenticator, tak ja tam ten model cely nepoužívám, ale daávám s itam jen DAO, či-li v podstatě je to jakoby přímo ta práce s DB, jak zminujes
- David Klouček
- Člen | 57
Potřebuju tam uživatelem pracovat, budu ho teda taky předávat parametrem. Ale je to zbytečný, je to jenom kvůli tomu, že to jinak nejde.
- Jiří Nápravník
- Člen | 710
No budeš pracovat s uživatelem, či-li s jeho identitou ne (NS\User->getIdentity())? NS\User je v podstatě jen service, kteráá má v sobě
Jinak to jde, pokud ji tam potrebuejs tedy potřebuješ. Nedávat do autentifikatoru stejnou modelovou třídu, který vyžaduje NS\User, bud jinou nebo přímo se zeptat databáze.