Získání základního info o přihlášeném uživateli
- akadlec
- Člen | 1326
Dělám teď jednu extension která má závislost na Nette\Security\User. Z tohoto uživatele potřebuji vytáhnout základní data pokud je obsahuje: name, email a website. Name bych chtěl mít jako povinné aby tam bylo, přeci jen je vhodné toho uživatele nějak identifikovat (tyto hodnoty se ukládají do db).
Odkud to ideálně brát? Z identity? udělat k tomu nějaký log aby případný jiný developer co by tu ext chtěl využít věděl že by bylo vhodné tam přidat konkrétní metody co by vraceli požadované hodnoty?
- Tomáš Votruba
- Moderator | 1114
Co by měla tvá extension rozšiřovat? S cílem se bude lépe odpovídat.
Předpokládám, že nehledáš pouhé
$this->user->identity->name
.
Osobně preferuji tahání dat z db pro případ, kdy si uživatel údaje změní (je třeba refreshnout identitu, což je zbytečné). Inspiroval jsem se nette-identity-doctrine, které toto řeší. Data se načítají lazy, tedy pouze při volání, a není třeba se starat o aktuálnost session.
- akadlec
- Člen | 1326
Konkrétně to je extension pro řešení komentářů napříč moduly. Jednoduše, při načtení stránky se vytvoří informace o uživateli (jméno, email, webstránka) a tyto informace se pak použijí při vytváření postu atd.
Jop předpokládáš dobře, hledám obyč jméno atd. Takže soudím že ideálně je tedy jít přes identitu.
Ano já konkrétně tak doctrine-identity používám, ale chtěl bych to mít bez téhle závislosti.
- Tomáš Votruba
- Moderator | 1114
Rozumim. Pouzit id uzivatele by bylo vhodnejsi, kdyby si uzivatel napr. zmenil jmeno.
- akadlec
- Člen | 1326
Jop to určitě ano, ale chcu se vyhnout závislosti na registrovaných uživatelích, resp. je možnost přidat komentář i jako guest či se lognout přes fb, twitter atd.
Idea je taková že pokud je uživatel přihlášen tak se jeho jméno, mail
a webstránky vytáhnou z identity s tím že minimálně jméno by mělo být
povinné v identitě.
Pak může být uživatel guest, takže jméno, email a webstránky si zadá
přímo do formuláře s tím že min. jméno by mělo být povinné
No a taky může uživatel využít přihlášení přes FB, Twitter, G+ atd.
ale čistě jen pro komentáře a tímpádem uživatel nemá identitu. O tomto
uživateli si uložím jeho id (fb, twitter,…) a pak si ty potřebné data
vytáhnu přes api.
Když se pak řeší zobrazení konkrétního příspěvku tak pokud se jedná o autora co je registrován v aplikaci tak se jeho jméno veme z DB to aktuální a pro ostatní se veme to co je uloženo. Nic lepšího mě nenapadlo, takto jsem to řešil v předchozí nonNette appce a kupodivu to fungovalo.
- Zax
- Člen | 370
Asi bych to řešil tak, že bych měl víc tabulek pro různé druhy uživatelů. U každého druhu uživatele si pak můžeš ukládat co potřebuješ (u fb uživatelů třeba profilový obrázek). Při vypisování bych se třeba podle příznakového sloupce (0=guest, 1=user, 2=fbuser, … – nevýhoda: nejdou použít správně cizí klíče, výhoda: snadnější rozšiřitelnost) nebo podle vyplněnosti cizích klíčů (user_id, fb_user_id, …) rozhodl, ze které tabulky to natahám.
Navíc nemusíš tahat data z API při každém requestu, prostě si je nacachuješ do příslušné tabulky v databázi (asi je dobrý jednou za čas data refreshnout třeba aby se načetly aktuální fb profilové obrázky).
A hlavně je pak všechno relativně oddělené a rozšiřitelné, když se za půl roku objeví nová populární služba s vlastním login API, tak to můžeš celkem snadno přidat, nebo se třeba můžeš rozhodnout, že to budeš chtít i na něco jiného, než komentáře atd.
Všechny entity by pak mohly mít metodu getUserData, která vrátí pole ve stejném formátu jako třetí parametr pro identitu a při výpisu komentářů si z toho snadno nataháš vše, co potřebuješ.
- akadlec
- Člen | 1326
Tak tak nějak v obecnosti to co uvádíš už ale řeším. Dělat další tabulky na to abych uložil identitu uživatele ze sociální sítě mi připadá moc zbytečné. Konkrétně avatary kešuju a stejně tak můžu kešovat ostatní data, ale krom jména a emailu mě žádná jiná data nezajímají. A samo že pořád volat api je blbost, proto ta keš.
A jak uvádíš že je pak snadné přidat jinou síť, tak v mém řešení je to snadnější, resp nemusím řešit přidání nějaké další tabulky, případně sloupce pro cizí klíč atd.
- Zax
- Člen | 370
Aha, tak na to bych si asi udělal nějaké public static properties
public static $web = 'www';
public static $email = 'email';
// ...
kde ‚www‘ a ‚email‘ jsou názvy klíčů v poli $user->identity->data. Když to pak někdo bude používat, tak si to v poho může změnit jak potřebuje nebo třeba nastavit na NULL pokud v identitě nic takového nemá.
Pochopil jsem už dotaz správně? :-P
- Šaman
- Člen | 2668
Moc magie škodí. Kdo používá nějaké ORM, nebo aspoň objektovou
obálku ála NDbT, tomu bude stačit vytáhnout si z databáze entitu/row
aktuálního uživatele. Jak, to už záleží na konrétní aplikaci,
v nejjednodušším případě v BasePresenteru, kde se z identity vezme jen
id
a rovnou se použije pro vrácení objektu.
P.S. Nevíte někdo, jestli se plánuje přejmenování některých automatických property aby se název uvolnil pro vlastní proměnné? (Třeba právě $presenter->user)
- Zax
- Člen | 370
@Šaman: Nejsou tyto proměnné v presenteru nastavené jako private? Tzn když podědíš UI\Presenter, tak si musíš tu službu sám injectnout, jinak se k ní nedostaneš.. nebo jsem něco přehlédl/špatně pochopil?
EDIT: BTW jaká magie? Když víš, že to pracuje s Nette\Security\User a znáš způsob vytažení dat z identity (který se x let nemění), tak co je na tom magického? Ty properties jsou jenom k tomu, aby si vývojář mohl natahat informace z identity a říct tomu doplňku, které klíče jsou k tomu potřeba. Navíc když už to máš v identitě, proč kvůli tomu volat další dotaz na databázi?
Editoval Zax (8. 5. 2014 3:10)
- jiri.pudil
- Nette Blogger | 1034
@akadlec: Udělal bych si interface s příslušnými gettery a vyžadoval, aby ho entita uživatele implementovala. Pokud údaj není k dispozici, vrátí se NULL (nebo něco, s čím tvé rozšíření dokáže pracovat).
- MartinitCZ
- Člen | 580
Já osobně data o uživateli vždy dotahuji z db dle Id.
$this->user->identity
považuji za nepoužitelné, jelikož
mi nikdo nezaručí aktuálnost dat. V tomto zápisu je mi naopak zaručena
neuktuálnost dat.
- akadlec
- Člen | 1326
Tak ještě jednou o co se snažím.
Představte si extension která vám řeší komentáře k položkám (články, produkty, události, atd.) Tato extension by měla být nezávislá od samotné aplikace, takže nějaké tahaní info z DB podle nějakého ID by ji takto zabilo. Proto se k získání informací o uživateli (id, jméno, email, web) použije (jak jsme se již zde dohodli) identita. Takže tyto potřebné data/metody bude muset implementovat ten kdo bude chtít tu ext použít přidáním do identity.
@jiri.pudil: to je fajn nápad, jen asi by to znamenalo že i když to není potřeba tak by si musel každý vytvořit svou třídu identity.
@zax: no to nevím zda by bylo ok. Jako ja bych za required chtěl minimálně jméno, takže to vytažení z identity bych obalil try/catch a pokud by identita neobsahovala požadované pole (jméno) vyhodila by se výjimka, pokud by neobsahovala email a jméno tak by se to ignorovalo.
@Šaman: no já osobně to mám na doctrine2 a pracuje to s entitou, ovšem chtěl bych to udělat uni a fungovalo to i třeba s NDbT, ale s tímto nemám zkušenosti :(
Resp. má cenu tu extension pak zveřejňovat? Obecně řeší komentáře (přidání a zobrazení). Komentáře je možné zanořit do stromu, je možné na ně odpovídat, vytvářet komentáře admina atd. Je zde podpora blacklistu na nevhodná slova,jména,ip.....ale vyžaduje to kooperaci se samotnou aplikací, tj. předání z aplikace načtench komentářů, samotné uložení komentáře atd.
- Zax
- Člen | 370
@martinit: nic ti nebrání rozšířit si UserStorage tak, aby ti při každém requestu načítal aktuální data z db. Pak se klidně můžeš na identitu spolehnout.
@jiri.pudil: jo, to je asi čistější než můj nápad. A nedalo by se to rovnou zkombinovat s mým řešením? Tj. udělat nějakou základní implementaci v tomto stylu:
interface IUser {
public function getName();
public function getWww();
// ...
}
class User implements IUser {
public static $name = 'name';
public static $www = 'www';
// ...
protected $user;
public function __construct(Nette\Security\User $user) { // nebo je lepší rovnou Identity?
$this->user = $user;
}
public function getName() {
$key = self::$name;
return $this->user->identity->$key;
}
// ...
}
Neboli – proč vytvářet další „opruz“ pro člověka, který to má používat, když to není nezbytně nutné?
Editoval Zax (8. 5. 2014 13:59)