Jak rozsirit UserStorage?
- juzna.cz
- Člen | 248
Stahl jsem aktualni nette z gitu a snazim se nastavit si vlastni UserStorage, aby mi nacitalo uzivatele z Doctrine. Chtel bych, aby se do session ukladalo pouze id uzivatele, a pri kazdem requestu se uzivatel nacetl z DB.
Myslel jsem, ze neco takoveho by mohlo fungovat:
class MyUserStorage extends UserStorage {
public function setIdentity(IIdentity $identity = NULL) {
// ukladma pouze id
$this->getSessionSection(TRUE)->identityId = $identity ? $identity->getId() : null;
return $this;
}
public function getIdentity() {
if(!$session = $this->getSessionSection(FALSE)) return NULL;
if(!$id = $session->identityId) return NULL;
// nactu z doctrine
return $this->em->getRepository(IdentityEntity::getClassName())->find($id);
}
}
Toto vsak nefunguje, protoze metoda getSessionSection mi cele session smaze, jestlize v nem neni instance IIdentity. Musim tedy zkopirovat tuto metodu a kvuli ni celou tridu (kvuli private properties).
Mate nekdo nejake elegantni reseni? (A tim nemyslim takove hromady kodu jako ma treba HosipLan v Kdyby)
Editoval juzna.cz (16. 1. 2012 12:10)
- Filip Procházka
- Moderator | 4668
Pošli si pull
189: - if (!$section->identity instanceof IIdentity || !is_bool($section->authenticated)) {
189: + if (empty($section->identity) || !is_bool($section->authenticated)) {
Já se toho kódu taky rád zbavím ;)
- David Grudl
- Nette Core | 8228
Ale na ten interface je navázáno všechno další. A jméno proměnné v session je věcí interní implementace, ne?
- pave.kucera
- Člen | 122
Dá se to docela jednoduše obejít, používám:
<?php
/**
* @param \Nette\Security\IIdentity
* @return UserStorage
*/
public function setIdentity(\Nette\Security\IIdentity $identity = NULL)
{
$this->identity = $identity;
if ($identity instanceof Model\UserEntity) {
$identity = new \Nette\Security\Identity($identity->getID());
}
return parent::setIdentity($identity);
}
/**
* @return \Nette\Security\IIdentity|NULL
*/
public function getIdentity() {
$identity = parent::getIdentity();
if (!$identity) {
return NULL;
}
// Find user
$identity = $this->userDao->find($identity->getId());
return $identity;
}
?>
- juzna.cz
- Člen | 248
Opet jsem narazil na tento stary problem. S pouzitim interfacu je vse v poradku, proti tomu zadna. Problem nastane, kdyz si chci trosku zmenit chovani UserStorage. Vetsinu logiky ale chci zachovat. Kopirovat si tuto tridu a zmenit v ni kousek kodu nechci, rad bych ji reusoval a pretizil metody.
Vnitrni implementace moji pretizene tridy by se mela chovat trosku jinak, a
to ze do session ulozi jen ID uzivatele. Metody {g/s}etIdentity si ze session
vytahnou co potrebuji a pretvori to na instanci IIdentity – a uz je na me,
jak si to udelam.
(sice je to detail, ale v ramci tohoto si zmenim i nazev promenne v session
na identityId/userId, aby davalo vice smysl)
Problem je, ze se UserStorage neda jednoduse pretizit prave kvuli tomu jednomu prikazu – musel bych vykopirovat celou metodu getSessionSecton.
(az budu doma u PC zkusim udelat pull request)
- juzna.cz
- Člen | 248
Pull Request a zde ukazka meho rozsireneho UserSrorage. Ted si tam muzu delat jakekoliv cachry machry a nemusim si vykopirovavat celou tridu z frameworku. To, co se kam uklada do session, lze nastavit ve 4 pretizenych metodach. Veskery zbytek logiky (expirace, kontrola browseru) zustane pekne v Nette a nemusim na ni sahat a funguje.
<?php
/**
* Extended Nette's storage for users - stores only ID to session and always loads full user from database
*
* @author Jan Dolecek <juzna.cz@gmail.com>
*/
class UserStorage extends Nette\Http\UserStorage
{
/** @var UserService */
private $userService;
/** @var User cached, loaded from database */
private $user;
public function __construct(\Nette\Http\Session $sessionHandler, UserService $userService)
{
parent::__construct($sessionHandler);
$this->userService = $userService;
}
public function setIdentity(IIdentity $user = NULL)
{
$this->user = $user;
$this->getSessionSection(TRUE)->identityId = $user ? $user->getId() : NULL;
return $this;
}
public function getIdentity()
{
if ($this->user) return $this->user;
$session = $this->getSessionSection(FALSE);
return $session && $session->identityId ? $this->user = $this->userService->fetch($session->identityId) : NULL;
}
protected function isSessionValid(SessionSection $section)
{
return !empty($section->identityId) && is_bool($section->authenticated);
}
protected function clearSession(SessionSection $section)
{
unset($section->identityId);
}
}
?>
- Majkl578
- Moderator | 1364
Není to tak dlouho, co jsem řešil totéž – integraci Doctrine entity
jako IIdentity. Došel jsem tehdy k řešení, které mi přišlo poměrně
čisté a bez problémů jej používám doteď. Princip je jednoduchý –
místo entity do storage ukládám jen jednoduchý objekt fake identity, která
udržuje ID, nic víc.
Zde je Gist.