Jak byste na to šli? (login form – komponenta?)

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

Zdravím. Chci se zeptat na docela obecnou věc. Už nějakou dobu se v Nette šťourám, ale jak dělám ještě X jiných věcí, tak postupuju dost pomalu.

Jedná se o to, že bych chtěl mít na stránce vždy nahoře login formulář (nebo místo něj napsáno „jste přihlášen jako…“) a to ve všech možných presenterech či views. Do teď jsem to dělal tak, že jsem měl na login extra presenter a action. Jak byste na to šli?

První, co mě napadlo, bylo, že jsem do BasePresenteru ze kterého všechny ostatní dědí přidal do startup() onen formulář. To funguje tak napůl, jakmile chci vytvořit instanci Identity, tak to hodí chybu

Cannot regenerate session ID after HTTP headers have been sent

Možná je chyba jinde, nevím.

Tak či tak, nevyplatilo by se udělat pro ten login komponentu?

pmg
Člen | 372
+
0
-
Cannot regenerate session ID after HTTP headers have been sent

Nejspíš bude problém v mezerách před značkou <?php v některém ze souborů index.php, bootstrap.php nebo v souborech s presentery. Také je možné, že máš někde zapomenuté dumpovací echo. Před otevřením session se totiž nesmí posílat žádný výstup do prohlížeče. Můžeš zkusit header('MyHeader: test'); aby ses dozvěděl, kde výstup začíná.


Nevím, jestli už jsem to někde nepsal, ale myslím, že ta hláška by měla znít after HTTP headers were sent, protože je to časová věta.


Tak či tak, nevyplatilo by se udělat pro ten login komponentu?

Deklarovat formulář v BasePresenter je vcelku legitimní. Ale z koncepčního hlediska se může stát, že ho nebudeš chtít zobrazit úplně na každé stránce a deklaraci radši přesuneš jinam. Pak by asi bylo správnější použít komponentu.

Ola
Člen | 385
+
0
-

Nene, myslím, že tohle v mezeře před <?php nebude. Pokud si to dobře pamatuju, tak pokud sem nezavolal Environment::getUser->getIdentity() dříve než v render fázi tak mi to taky psalo tuhle větu ..

pmg
Člen | 372
+
0
-

Vsadíme se? :-)

A nevolal jsi session poprvé až po render fázi, popř. v render fázi nějaké komponenty? Také je možné, že jsi v některé z předešlých fází zapomněl dumpovací echo. :-)

V případech, kdy se k session poprvé přistoupí až při vykreslování, je asi nejjednodušším řešením dát do startupu

$session = Environment::getSession();
if (!$session->isStarted()) {
	$session->start();
}

Nicméně ta CSRF protekce nebo Captcha (které session vyžadují) session vytvoří už při definici formuláře, takže Martinův problém toto nevyřeší.

Ola
Člen | 385
+
0
-

Jo, bylo to tou session, chtěl jsem to jenom navrhnout jako další (možná špatnou) variantu..

pmg
Člen | 372
+
0
-

Já to beru a jen jsem to okomentoval. Čím víc variant, tím lepší řešení. :-)

Martin Mates
Člen | 179
+
0
-

Šlo mi spíš o to, že jsem formulář vždy definoval v actionLogin a ten to vykreslil na extra stránku. jenže, když to chci mít všude a vykreslovat to v @layout, tak nevím, kam to mám dát. action metoda má svou url a svou šablonu pokud se nepletu. Zkusil jsem form definovat ve startup() v basePresenteru, je to správně? V beforeRender už je asi pozdě ne?

Hází to pořád tu chybu. Žádnou mezeru před PHP znackou nemam.

UZ TO FUNGUJE!! Bylo to mezerou na řádku 33 v jednom presenteru.. normální mezera mezi 2 metodama :-/ Díky kucííí!

Editoval Martin Mates (11. 4. 2009 11:54)

pmg
Člen | 372
+
0
-

BeforeRender by mělo stačit a je asi lepší. Použil bych to v kombinaci s createComponent.

normální mezera mezi 2 metodama :-/

A nebylo v té mezeře nějaké zapomenuté dumpovací echo? :-D Jinak bych si myslel, že je to vtip.

Editoval pmg (11. 4. 2009 12:11)

Martin Mates
Člen | 179
+
0
-

pmg napsal(a):

BeforeRender by mělo stačit a je asi lepší. Použil bych to v kombinaci s createComponent.

normální mezera mezi 2 metodama :-/

A nebylo v té mezeře nějaké zapomenuté dumpovací echo? :-D Jinak bych si myslel, že je to vtip.

Žádné dumpovací echo tam nebylo, to bych si vsim :-) Je to hodně divný. Píšu v NetBeans 6.5

Jan Jakeš
Člen | 177
+
0
-

Žádné dumpovací echo tam nebylo, to bych si vsim :-) Je to hodně divný. Píšu v NetBeans 6.5

Jseš si jistej, že to bylo tou mezerou? Pokud to je mezera uvnitř PHP kódu, tak to prostě neni možný :) Nehodil bys sem ten kousek kódu, kde to podle tebe bylo?

Martin Mates
Člen | 179
+
0
-

Juan napsal(a):

Žádné dumpovací echo tam nebylo, to bych si vsim :-) Je to hodně divný. Píšu v NetBeans 6.5

Jseš si jistej, že to bylo tou mezerou? Pokud to je mezera uvnitř PHP kódu, tak to prostě neni možný :) Nehodil bys sem ten kousek kódu, kde to podle tebe bylo?

<?php

/**
 * Users authenticator.
 */
class Auth extends Object implements IAuthenticator
{

    /**
     * Performs an authentication
     * @param  array
     * @return void
     * @throws AuthenticationException
     */
    public function authenticate(array $credentials)
    {
        $username = strtolower($credentials[self::USERNAME]);
        $password = strtolower($credentials[self::PASSWORD]);

        $row = dibi::select('*')->from('users')->where('login=%s', $username)->fetch();

        if (!$row) {
            throw new AuthenticationException("Uživatel '$username' nenalezen.", self::IDENTITY_NOT_FOUND);
        }

        if ($row->heslo !== md5($credentials[self::PASSWORD] . strtolower($credentials[self::USERNAME]))) {
            throw new AuthenticationException("Špatné heslo.", self::INVALID_CREDENTIAL);
        }

        if ($row->potvrzen != 1) {
            throw new AuthenticationException("Účet ještě nebyl potvrzen.");
        }

        unset($row->heslo);
        return new Identity($row->login, NULL, $row);
    }
/* TADY JSEM ODSTRANIL MEZERU A ZACALO TO FUNGOVAT */
}
?>

Nic jiného jsem neměnil. Když tam tu mezeru dám zpět, tak to jde bez problémů. Debug hlásil Output started at line 33 (nyní už je to 37).. na té řádce nebylo nic, jen tahle mezera (konec řádku), dal jsem to pryč a viola!

Jan Jakeš
Člen | 177
+
0
-

Nic jiného jsem neměnil. Když tam tu mezeru dám zpět, tak to jde bez problémů. Debug hlásil Output started at line 33 (nyní už je to 37).. na té řádce nebylo nic, jen tahle mezera (konec řádku), dal jsem to pryč a viola!

No tak že by to bylo mezerou uvnitř PHP kódu, to je vážně nesmysl a i kdyby tam byl nějakej neviditelněj znak, tak se nemůže bez echa vypsat, to by nahlásil chybu syntaxe interpret… Neni možný že si třeba upravil víc věcí a nevšim sis přesně, kdy to začalo fungovat? Ono by to vypsalo tu samou chybu, kdyby např. ten řádek s dibi obsahoval login=%s a řádek s Identity např. $row->username, klidně si to zkus. Např takto:

$row = dibi::select(‚*‘)->from(‚users‘)->where(‚login=%s‘, $username)->fetch();

return new Identity($row->username, NULL, $row);

Protože u $row->username ti nějaká funkce vypíše chybu, že username není definováno (protože výše bylo uvedeno uveden akorát název login), no a výpis té chyby způsobí, že nelze regenerovat session, protože už bylo cosi vypsáno… Ten výpis ty ale nejspíš nevidíš, protože je pohlcen laděnkou. Např. ve Firebugu ho ale vidět můžeš…

Ola
Člen | 385
+
0
-

Laděnku by mohl schovat přes „zavírátko“ vpravo nahoře..

Jan Jakeš
Člen | 177
+
0
-

Nojo :) A pak je tedy naprosto jasně vidět, co se vypsalo, a co tedy způsobilo nemožnost regenerace sessions…

Editoval Juan (14. 4. 2009 10:23)