How to Return to an Earlier Page?

What if a user fills out a form and his login expires? To avoid losing the data, we save the data in the session before redirecting to the login page. In Nette, this is a piece of cake.

The current request can be stored in the session using the storeRequest() method, which returns its identifier as a short string. The method stores the name of the current presenter, the view and its parameters. If a form was also submitted, the values of the fields (except for the uploaded files) are also saved.

The request is restored by the restoreRequest($key) method, to which we pass the retrieved identifier. This redirects to the original presenter and view. However, if the saved request contains a form submission, it will forward to the original presenter using method forward(), pass the previously filled values to the form and let it be redrawn. This allows the user to resubmit the form and no data is lost.

Importantly, restoreRequest() checks that the newly logged in user is the same one who originally filled out the form. If not, it discards the request and does nothing.

Let's demonstrate everything with an example. Let's have a presenter AdminPresenter in which data is being edited and whose method startup() checks if the user is logged in. If he is not, we redirect him to SignPresenter. At the same time, we save the current request and send its key to SignPresenter.

class AdminPresenter extends Nette\Application\UI\Presenter
{
	protected function startup()
	{
		parent::startup();

		if (!$this->user->isLoggedIn()) {
			$this->redirect('Sign:in', ['backlink' => $this->storeRequest()]);
		}
	}
}

The SignPresenter presenter will contain a persistent $backlink parameter to which the key is written, in addition to the log-in form. Since the parameter is persistent, it will be carried over even after the login form is submitted.

class SignPresenter extends Nette\Application\UI\Presenter
{
	/** @persistent */
	public $backlink = '';

	protected function createComponentSignInForm()
	{
		$form = new Nette\Application\UI\Form;
		// ... add form fields ...
		$form->onSuccess[] = [$this, 'signInFormSubmitted'];
		return $form;
	}

	public function signInFormSubmitted($form)
	{
		// ... here we sign the user in ...

		$this->restoreRequest($this->backlink);
		$this->redirect('Admin:');
	}
}

We pass the key of the saved request to the restoreRequest() method and it redirects (or forwards) to the original presenter.

However, if the key is invalid (for example, no longer exists in the session), the method does nothing. So the next call is $this->redirect('Admin:'), which redirects to AdminPresenter.