Sessionの保持するタイミングについて
デフォルトの実装はrequest処理中、sessionで管理した内容をresponseを返す前に保持しなくて、responseを返した直後にsessionを保持(terminateファンクション中で)する。
このやり方の問題点は次のrequest(redirectなど)がsessionの保持処理が終わる前に来ると、前のrequestで保持しようとしたsessionの内容がゲットできないので、session依存の機能がく地獄に落ちる。なぜこんな実装になっているのかは良く分からない。
自分が考えた解決案は
StartSessionを継承して、terminateファンクションを空っぽにし、セッション保持処理をhandleファンクションでする。
世の中は完璧な人がない、
世の中は完璧なコードがない、
絶対正しい知識がない、条件付きじゃないと、
真実は真実にある。
use Closure;
use Illuminate\Support\Arr;
use Illuminate\Session\SessionInterface;
use Symfony\Component\HttpFoundation\Cookie;
use Symfony\Component\HttpFoundation\Response;
use Illuminate\Session\Middleware\StartSession as IlluminateStartSession;
class StartSession extends IlluminateStartSession
{
public function handle($request, Closure $next)
{
$response = parent::handle($request, $next);
if ($this->sessionHandled && $this->sessionConfigured() && !(env('APP_TYPE') == 'API')) {
$this->manager->driver()->save();
}
return $response;
}
protected function addCookieToResponse(Response $response, SessionInterface $session)
{
if ($this->sessionIsPersistent($config = $this->manager->getSessionConfig())) {
$response->headers->setCookie(new Cookie(
$session->getName(), $session->getId(), $this->getCookieExpirationDate(),
$config['path'], $config['domain'], Arr::get($config, 'secure', false)
));
}
}
public function terminate($request, $response)
{
// Do nothing here
// save session in handle function
}
}
terminateファンクションについてのドキュメント:
https://laravel.com/docs/5.1/middleware#terminable-middleware
ソースコード:
https://github.com/illuminate/session/blob/master/Middleware/StartSession.php
別の解決案
全てのsessionに格納したい値を格納した後、手動で Session::save()
呼ぶ方法がありますが、全て格納されているのかの判断が難しいです。laravel frameworkや、middlewareの中などでもsesssionを使う可能性があるから。