前のページに戻るには?
ユーザーがフォームに入力している最中にログインのセッションが切れたら、どうなるでしょうか。データを失わないよう、ログインページにリダイレクトする前に現在のリクエスト(フォームのデータを含みます)をセッションに保存できます。Nette では、これが驚くほど簡単です。
現在のリクエストは storeRequest()
メソッドでセッションに保存できます。このメソッドは、保存したリクエストの一意な識別子(短い文字列)を返します。現在のプレゼンターの名前、そのビュー、パラメータが保存されます。リクエストの一部としてフォームが送信されていた場合は、フィールドに入力された値(アップロードされたファイルを除きます)も保存されます。
リクエストは restoreRequest($key)
メソッドで復元します。先ほど得た識別子を渡してください。このメソッドはユーザーをもとのプレゼンターとビューに戻します。ただし保存されたリクエストにフォームの送信が含まれていた場合、restoreRequest()
はリダイレクトの代わりに forward()
メソッドを使います。以前に入力された値をフォームに戻し、もう一度描画できるようにします。おかげでユーザーは、入力したデータを失わずにフォームを再送信できます。
重要なのは、restoreRequest()
が、新しくログインしたユーザーがもとのフォームを送信したユーザーと同じかどうかを確認する点です。別のユーザーなら、保存されたリクエストは復元されず、メソッドは何もしません。安全性が高まります。
例で見てみましょう。データを編集する AdminPresenter があるとします。その
startup() メソッドはユーザーがログインしているかを確かめます。していなければ
SignPresenter にリダイレクトします。同時に storeRequest()
で現在のリクエストを保存し、そのキー($backlink)を
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 にはログインフォームのほかに、キーを保持する永続パラメータ
$backlink
があります。パラメータが永続なので、ログインフォームを送信したあとも値が保たれます。
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;
// ... フォームの項目を追加します ...
$form->onSuccess[] = $this->signInFormSuceeded(...);
return $form;
}
private function signInFormSuceeded($form)
{
// ... ここでユーザーをログインさせます ...
$this->restoreRequest($this->backlink);
$this->redirect('Admin:');
}
}
保存したリクエストのキー($this->backlink)を restoreRequest()
メソッドに渡します。すると、ユーザーをもとのプレゼンターとビューにリダイレクト(または
forward)します。
ただしキーが正しくない場合(たとえばセッションから失効している場合)、メソッドは何もしません。ですから、続く
$this->redirect('Admin:') の呼び出しがフォールバックとして働き、AdminPresenter
のような既定のページにリダイレクトします。