Session error when using nette/forms in other app
- mikeb
- Member | 31
Hello
I'm brand new to nette and at this stage just using the nette/forms (instaled
via composer) in a legacy app which does a session start before the page with
the nette form is called. i get the following error:
Deprecated: Missing annotation @property for Nette\Http\Session::$started used in *****\vendor\nette\http\src\Http\Session.php:410 in ****\vendor\nette\utils\src\Utils\SmartObject.php on line 116
Fatal error: Exception in Nette\Forms\Form::__toString(): Unable to set 'session.use_only_cookies' to value '1' when session has been started by session.auto_start or session_start(). in *****\vendor\nette\http\src\Http\Session.php:410 in ****\vendor\nette\forms\src\Forms\Form.php on line 655
i had to silence tracy to see the error as tracy just said server error and it wasn't an error in my php logs. my guess is there's a clash in how sessions are handled. If i eliminate all traces of the other app my nette/forms code runs fine, which at this stage is just the bootstrap3-rendering.php examples recycled from here.
its on an xampp server with php 5.6.8. can anyone suggest a solution? is it around session management? is it a matter of starting nette http before anything else? if so, how?
thanks
Mike
Last edited by mikeb (2016-09-21 12:46)
- mikeb
- Member | 31
further… it appears the sessions exceptions are not encountered until the
form is echoed via the Forms\Form.php __toString() magic method which manages
the rendering.
So even when i start Nette before the other legacy app, I can't work around
Nette's requirement for starting a session…
maybe override the __toString() method? tho that sounds very hacky.
or is it that Nette forms just won't play well with other frameworks or apps
that also require session?
all comments appreciated
Mike
- mikeb
- Member | 31
OK one more comment. the form I am playing with adds CSRF protection:
//$form->addProtection('Security token has expired, please submit the form again');
if I comment out this line then the session error no longer appears.
I assume this feature changes the rendering process and bumps into the session
clash.
I don't understand Nette well enough to know if this is intentional (i guess
session holds the CSRF token?) but it does look like a show stopper.
???
- mikeb
- Member | 31
in \vendor\nette\http\src\Bridges\HttpDI\SessionExtension.php
i changed
$defaults = ['autoStart' => 'true',...
and even when I
use Nette\Forms\Form;
$form = new Form;
as the first functions of the legacy app it still throws the exception when the form is echoed (rendered).
??? all ideas welcome!
Last edited by mikeb (2016-09-22 10:14)
- mikeb
- Member | 31
ok i think I have a work-around/result using the forms module alone with a legacy app that also sets session. that is, generate and add a token as a hidden required element and add a custom validator to that:
1. make a token (I'm happy with one token per sesssion as session is destroyed with login/logout)
if(!isset($_SESSION['mb_token'])){
if(!isset($_SESSION)){
session_start();
}
$_SESSION['mb_token'] = md5(uniqid(rand(), TRUE)); // MB: add a token for the posts, ajax
}
2. then make a custom validator:
class MyValidators
{
static function checkToken($item){
if(!isset($_SESSION['mb_token'])){
return FALSE;
}
if($item->value==$_SESSION['mb_token']) return true;
return false;
}
}
3. then add a hidden input to the form:
$form->addHidden('mb_token', $_SESSION['mb_token'])
->setRequired(true)
->addRule('MyValidators::checkToken', 'Your page has timed-out - please reload the page and try again');
I'm sure there is a more elegant and nette-friendly solution but this appears
to work. and I can now use nette forms with my project and have some CSRF
protection!
(it would be nice it future versions of nette didn't have such insistent
requirements for session so they could play nicely with other apps, assuming
security isn't compromized)
HTH
Mike
Last edited by mikeb (2016-09-23 02:30)