Come tornare a una pagina precedente?

Cosa succede se un utente sta compilando un form e la sua sessione di login scade? Per non perdere i dati, possiamo salvare nella sessione la richiesta corrente (dati del form compresi) prima di reindirizzare alla pagina di login. In Nette è sorprendentemente semplice.

La richiesta corrente si può salvare nella sessione con il metodo storeRequest(). Questo metodo restituisce un identificatore univoco (una stringa breve) della richiesta salvata. Il metodo salva il nome del presenter corrente, la sua vista e i suoi parametri. Se nell'ambito della richiesta è stato inviato un form, vengono salvati anche i valori inseriti nei campi (esclusi i file caricati).

La richiesta si ripristina con il metodo restoreRequest($key), al quale passate l'identificatore ottenuto in precedenza. Questo metodo reindirizza l'utente al presenter e alla vista originali. Se però la richiesta salvata comprendeva l'invio di un form, restoreRequest() usa il metodo forward() invece di reindirizzare. Ripassa al form i valori compilati in precedenza e ne permette il rendering. L'utente può così reinviare il form senza perdere i dati inseriti.

Cosa essenziale, restoreRequest() verifica che l'utente appena connesso sia lo stesso che aveva inviato il form. Se l'utente è diverso, la richiesta salvata non viene ripristinata e il metodo non fa nulla, il che aumenta la sicurezza.

Illustriamolo con un esempio. Consideriamo un AdminPresenter in cui si modificano dei dati. Il suo metodo startup() verifica se l'utente è connesso. In caso contrario l'utente viene reindirizzato a SignPresenter. Allo stesso tempo salviamo la richiesta corrente con storeRequest() e ne passiamo la chiave (il $backlink) a SignPresenter.

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

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

SignPresenter conterrà, oltre al form di login, un parametro persistente $backlink in cui è salvata la chiave. Poiché il parametro è persistente, il suo valore si conserva anche dopo l'invio del form di login.

use Nette\Application\Attributes\Persistent;

class SignPresenter extends Nette\Application\UI\Presenter
{
	#[Persistent]
	public string $backlink = '';

	protected function createComponentSignInForm()
	{
		$form = new Nette\Application\UI\Form;
		// ... aggiunta dei campi del form ...
		$form->onSuccess[] = $this->signInFormSuceeded(...);
		return $form;
	}

	private function signInFormSuceeded($form)
	{
		// ... qui l'utente viene connesso ...

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

Passiamo la chiave ($this->backlink) della richiesta salvata al metodo restoreRequest(). Esso reindirizza (o inoltra) poi l'utente al presenter e alla vista originali.

Se però la chiave non è valida (per esempio è scaduta dalla sessione), il metodo non fa nulla. La chiamata successiva $this->redirect('Admin:') funge quindi da ripiego e reindirizza a una pagina predefinita, come AdminPresenter.