Získání základního info o přihlášeném uživateli

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

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
+
0
-

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
+
0
-

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
+
0
-

Rozumim. Pouzit id uzivatele by bylo vhodnejsi, kdyby si uzivatel napr. zmenil jmeno.

akadlec
Člen | 1326
+
0
-

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
+
0
-

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
+
0
-

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
+
0
-

Pak jsem asi nepochopil dotaz, teď mi to zní jako že ti všechno funguje… nebo se prostě ptáš na best practice? S tím ti bohužel moc nepomůžu :-(

akadlec
Člen | 1326
+
0
-

;) No spíše se ptám jak řešit to vytažení dat o přihlášeném uživateli tak aby to šlo integrovat i do appky kde třeba nebude u uživateli info o webstránce či emailu ;)

Zax
Člen | 370
+
0
-

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
+
0
-

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
+
0
-

@Š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
+
0
-

@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
+
0
-

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
+
0
-

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
+
0
-

@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)