Autor Zpráva
SwimX
Profil
Dobrý den,

hraju si s Nette a chtěl byc využít k přihlašování uživatelů jejich připravené řešení. Ale nedaří se:

use Nette\Http\User;

class CUser extends Nette\Object implements NS\IAuthenticator
{
    protected $user;
    
    public function __construct ( ) {
        ...
        $this -> user = Nette\Environment::getUser();
    }

   public function loginForm ( ) {
    
        $form = new Form;
        ...
        if ( $form -> isSubmitted() && $form -> isValid() ) {
            $values = $form -> getValues();
            $this -> authenticate ( array ( $values['login'], $values['password'] ) );
        }
        
        if ( ! $this -> user -> isLoggedIn ( ) ) {
             ....
        }
        else {
            .....
        }
    }
    
    public function authenticate( array $credentials )
    {
        list ( $login, $password ) = $credentials;
        
        ... sql select
        if ( ! $row )
            return;
            
        $this -> user = new Security\Identity( $row ['id'] );
        $this -> data = @ array_merge( $this -> data, $row );
    }
}


Dělám něco špatně? :-) Chybová hláška:
atal error: Uncaught exception 'Nette\InvalidStateException' with message 'Unable to set 'session.gc_maxlifetime' to value '10800' when session has been started by session.auto_start or session_start().' in C:\wamp\www\hotelpersonal.cz\libs\Nette\Http\Session.php on line 432

mám nastartovat sessiony nějak jinak? ani nevím, že by to eště jinak šlo...


Děkuji za rady
joe
Profil
Tenhle kód jsi vážně našel u Nette?

Tam se nepřepisuje konstruktor, pro vytváření komponent slouží továrničky - protected metody začínající na createComponentLoginForm()

Nemáš u formuláře $form->addProtected()? Pokud ano, musíš sessions nastartovat dřív, dává se to do bootstrapu:

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


Jinak fórum pro Nette je na http://forum.nette.org/cs/
SwimX
Profil
joe:
ne, todle je můj kód. Našel jsem, že je potřeba mít třídu vycházející z Nette/Object a implementující NS\IAuthenticator
s metodou authenticate( array $credentials ) která vrací identitu (metodu si mám napsat sám - kvůli DB a tak, to mám) viz http://doc.nette.org/cs/security

v návodu používají "službu user, což je objekt třídy Nette\Http\User" jenže prostě mají $user ... a kde se vzal tam napsáno není, tak jsem našel
$this -> user = Nette\Environment::getUser();
todle, asi by to i fungovalo, jen ty sessiony.

Sessiony startuju na začátku index.php a pak teprve includuji soubory s těmito třídami. Sessiony mi normálně fungují, nechápu, proč to hodí error -
unable to set 'session.gc_maxlifetime' to value '10800' when session has been started by session.auto_start
Ugo
Profil *
me se zda, ze je tam nekde volake ini_set a tomu proste vadi, ze session uz bezi, koukal si do toho souboru kde ta chyba udajne je co tam vlastne je? ... btw. co na to rika ladenka, ma k tomu nejakych slov? :)
SwimX
Profil
Ugo:
laděnku nepoužvám, vubec nepoužívám šablony.
SwimX
Profil
Ugo:
měl si pravdu a já sem se asi vubec nezamyslel :-) snaží se to změnit hodnoty v už běžících sessionách, ale stačí

ini_set("session.gc_maxlifetime", "10800");
dát před
session_start ( );
a už se to nesnaží a jsme oba spokojeni.

Díky, taková blbina zas :-)
joe
Profil
SwimX:
laděnku nepoužvám, vubec nepoužívám šablony.
Takže používáš jenom část Nette.
SwimX
Profil
joe:
ano, doteď jsem frameworky moc nepoužíval, s Nette si hraju na jednom větším projektu. Postupně zjišťuju, že se mi hodně líbí, ale eště chvilku potrvá, než ho využiji celé.

A to přihlašování mě pořád trápí - teď už bez errorů, není někde hezčí návod než sem tu odkázal?
Majkl578
Profil
[#1] SwimX:
Tenhle kód je špatně. Princip SRP říká, že každý objekt má jen jednu zodpovědnost. Tvoje třída CUser (jak jsi přišel na ten divný název?) se stará o a) autentikaci, b) vykreslení a zpracování formuláře.

[#2] joe:
V nové verzi Nette je Environment deprecated a používá se jiných technik (Dependency Injection - Nette\DI).

[#5] SwimX:
Laděnka se šablonami vůbec nesouvisí, jde o dva naprosto nezávislé a funkčně odlišné celky. Laděnka slouží k debugování.

[#6] SwimX:
Tenhle kód by v aplikaci s Nette neměl co dělat. Pokud používáš Nette session, měl bys využívat metodu Nette\Http\Session#start. Nette si prostředí konfiguruje samo.

[#8] SwimX:
Dám ti jednu radu - s problémy s Nette se obracej přímo na Nette fórum, kde je mnohem vyšší koncentrace lidí, kteří ten framework dobře znají a mohou konkrétně poradit. Ještě užitečnější může být Nette místnost na Jabberu kde nás bývá kolem 20-30 online.
SwimX
Profil
Majkl578:
Tenhle kód je špatně. Princip SRP říká, že každý objekt má jen jednu zodpovědnost
mám tam informace o živateli - pokud není přihlášen není v něm nic moc - voláním login form vypíši formulář pro login nebo kdo je přihlášen - pokud se odešle, tak se zavolá CUser -> autenthicate. Pořád to má co do činění s userem tak jsem to nechal v jedné třídě.

CUser (jak jsi přišel na ten divný název?)
Class User - uživatel - protože mi to zastřešuje metody pro uživatele

Pokud používáš Nette session
ani snad jsem to neměl v plánu :-) ale asi je využívám - s nette opravdu začínám, díky za radu.

Od teď otravuji na jabberu ;-)

Díky moc
joe
Profil
Majkl578:
V nové verzi Nette je Environment deprecated a používá se jiných technik (Dependency Injection - Nette\DI).
Ano je, ale neznamená, že ho nejde používat.

Tak tedy
$session = $container->session;
if(!$session->isStarted()) $session->start();


... kde $container je DI\Container
SwimX
Profil
require_once '../../libs/Nette/loader.php';
    
    $container = new Nette\DI\Container;

    $session = $container -> session;
    if( ! $session -> isStarted ( ) ) 
            $session -> start ( );


 Fatal error: Uncaught exception 'Nette\DI\MissingServiceException' with message 'Service 'session' not found.' in C:\wamp\www\hotelpersonal.cz\libs\Nette\DI\Container.php on line 147
Majkl578
Profil
joe:
Ano je, ale neznamená, že ho nejde používat.
Jistě, ale používat ho je špatné. Environment je teď už jen statická a smyslpostrádající obálka nad globálním kontejnerem.

[#12] SwimX:
Kontejner sám o sobě žádné služby nemá, musí se do něj prvně registrovat. Při použití Nette MVP se to děje automaticky při načtení konfiguračního souboru. Mimo MVP je to o něco složitější a musel bys ty služby nejspíš registrovat do kontejneru ručně.
SwimX
Profil
Majkl578:
asi bych potřeboval nějaký návod - nějaký tutorial. Nebylo by?

a trochu jiná otázka, teď mám

if ( ! $_SESSION [ 'user' ] )
$_SESSION [ 'user' ] = new CUser;

pak volám $_SESSION [ 'user' ] -> LoginForm ( ); když se odešlou data - tak se v private proměnné nastavi loggedIn na true a je to.
Ale nějak záhadně se to špatně ukládá do sessiony. To takle dělat nemůžu?
atal error: main() [function.main]: The script tried to execute a method or access a property of an incomplete object. Please ensure that the class definition "CUser" of the object you are trying to operate on was loaded _before_ unserialize() gets called or provide a __autoload() function to load the class definition in C:\wamp\www\hotelpersonal.cz\www\administrace\includes\header.php on line 13
joe
Profil
SwimX:
Nejprve se nauč s Nette...

Majkl578:
Jistě, ale používat ho je špatné.
Použít se dá, tečka :-) Například v modelech mi to přijde daleko jednodušší, neý to "pracně" nastavovat.
Majkl578
Profil
[#15] joe:
Použít se dá, tečka :-)
Používat se dá i čisté PHP. Ale proč používáme frameworky? Protože to je přínosné. A to samé se dá říct o DI vs. Environment. :)

Například v modelech mi to přijde daleko jednodušší, neý to "pracně" nastavovat.
To je čistá spekulace. Shodou okolností jsem na tohle téma psal příklad do Nette kuchařky. Použití mi přijde praktičnější než soustavné volání Environment::*.

Pokud chceš pokračovat na tohle téma, stav se na Jabberu, tady se zas držme tématu.

[#14] SwimX:
Ta chyba říká, že se snažíš přistoupit k objektu (serializovaném v session) ještě dřív, než je načtená jeho třída, PHP tak nezná třídu toho objektu. Nicméně serializovat ten objekt je stejně hloupost. Taková informace patří do session samotná, ne celý objekt. Viz řešení Nette\Http\User.
Nejjednodušší pro tebe asi bude, když u formulářů nebudeš používat ochranu (addProtected), která vytváří tuhle závislost. Stejnou feature si můžeš implementovat sám - podědíš Nette\Forms\Form, překryješ metodu addProtection a upravíš to tak, aby se využívalo přímo $_SESSION. (Je to ale ošklivé řešení.)
joe
Profil
Majkl578:
...
Super, tenhle článek jsem ještě nečetl, podívám se na něj, díky.

Ono to bude asi tím, že jsem prostě na ten Environment zvyklý, dřív to tak bylo, tak proč to měnit, když to funguje :-)

[#14] SwimX:
Já nějak nevím, proč nepracuje se sessions přes Nette a používá $_SESSION, které vůbec není potřeba. Měl by se podívat na nějaké příklady co a jak.

http://doc.nette.org/cs/getting-started
SwimX
Profil
Majkl578:
Ta chyba říká, že se snažíš přistoupit k objektu (serializovaném v session) ještě dřív, než je načtená jeho třída, PHP tak nezná třídu toho objektu.
tak tomu ale není.
mám
require "class_cuser.php";
if ( ! $_SESSION [ 'user' ] )
$_SESSION [ 'user' ] = new CUser;


spíše je potom problém: $_SESSION [ 'user' ] -> metoda. Tomudle se nechce.

joe:
Měl by se podívat na nějaké příklady co a jak.
To jsem četl a asi 10 tabů tu s tím ještě mám otevřených. Ale asi jsem natvrdlý, tendle návod mi zrovna 2x nepomáhá. :-)
joe
Profil
SwimX:
Nikde se nepoužívá
require()

pokud teda jsou třídy v adresářích co je v robot loaderu, který to dělá za tebe (je možné si tam přidat další v configu).

Nepracuje se $_SESSION, ale v presenterech s $this->getSession() / $this->session

Pokud se zajímáš o přihlášení, ve složkách ve stáhnutém Nette najdeš taky složku sandbox, tu si zkopíruj a zkus spustit.
Majkl578
Profil
[#18] SwimX:
To require musí být ještě před session_start, jinak vznikne objekt typu __PHP_Incomplete_Class a při přístupu bude psát to co jsi uvedl.

[#19] joe:
Měj na paměti, že používá jen nějaké části Nette a RobotLoader zřejmě ne. Nette třídy se načítají tak jako tak automaticky, ale ty jeho už bez RobotLoadera ne.
SwimX
Profil
Majkl578:
aha, díky moc, to jsem vubec neznal. Objekt __PHP_Incomplete_Class jsem viděl, ale nenapadlo mě, že musí být třída před session_start...

Měj na paměti, že používá jen nějaké části Nette
přesně tak, používám jen části, nemám čas to teď tolik zkoumat, musím taky projekt dokončit - v nette se mi líbily formuláře - takže to nakonec vypadá, že používám jen ty. Už jsem si napsal vlastní přihlašovaní, uložil do sessiony jenom true/false isLoggedIn a data o uživateli. Objekt mám jenom v proměnné. Je to tak lepší ("čistší") než ho serializovat do sessiony?
joe
Profil
Majkl578:
Pak jsem mu jenom nerozumněl, čekal jsem, že ho bude využívat celé ;-)
SwimX
Profil
joe:
časem bych rád :-))

Vaše odpověď

Mohlo by se hodit


Prosím používejte diakritiku a interpunkci.

Ochrana proti spamu. Napište prosím číslo dvě-sta čtyřicet-sedm:

0