#0.はじめに
####この記事について
#####この記事は**「Requestインスタンス」**を用いたセッションに関する記事です。
Laravelを用いた共同開発講座に参加させていただきました。
その中で一際難しく感じたセッションを用いたカート機能の実装についてまとめたいと思います。
同じように悩む誰かの一助になれば幸いです。
転職前の若造の乱筆ですがよろしくお願いいたします。
間違い等あれば喜んで訂正させていただきます。
####簡単に自己紹介
・医療職5年目
・完全独学6ヶ月後、共同開発講座に参加
・転職まであと○○(?)
ではさっそく参ります。
#1.セッションとは
####セッションて何?
【セッション = データを保存しておく仕組み】
です。
よくある"session"の説明 >>> 「アクセスの開始から終了までの一連の通信」
実際の"session"のイメージ >>> 「カギ」とか「合言葉」みたいな
という感じに、よくある説明と実際の掴みどころが少し違うような気がします。
よくある説明の通り、実現したいことは「アクセスの開始から終了までの一連の通信」を成り立たせることです。
SNSの場合毎回ログインせずとも、なぜかログイン後の画面からスタートできます。
これは一度ログインしたユーザーの情報を、サーバーが覚えてくれているから実現できます。
ショッピングサイトの場合でも、商品をカートに入れたあとにまたショッピングを楽しむにはカートに入れた商品のデータを保存しておく必要があります。
そのデータを保存するためにセッション機能があります。
「セッション機能をなぜ使うのか?」
この問に一言で答えるなら
「ステートレスなプロトコルをステートフルなプロトコルにするために使う」
となります。
これを超具体的に解説すると下記のようになります。
####具体例で解説
①あるuserがSNSに初回ログインした時にクライアントは、サーバー(Laravel)に合言葉(セッション情報)を渡します。
②サーバーは合言葉を覚えます。
③userはSNSを閉じます(別のサイトに飛ぶとします)
④(サーバーはまだ覚えてます。)
⑤userはSNSのログイン後画面に戻ります。(合言葉を言う)
⑥サーバーはuserを識別し、歓迎してログイン後の状態にする。(合言葉を確認)
⑦ログインされた状態が保たれています(ステートフル!!)
※セッション機能がないともう一度ログインしないといけません(ステートレス。。)
つまり
ステート(状態)レス === (ログイン)状態が保てない
を
ステート(状態)フル === (ログイン)状態を保てる
ようにするのがセッション機能です。
おそらくこれだけでは不足だと思いますので
参考になり、わかりやすかった記事を掲載させていただきます。
https://qiita.com/Yametaro/items/9b65a21940e001554719
https://umaroidblog.com/webtechnology1
#2.セッションを使うと何ができる?
①ログイン状態のキープ
②ショッピングカート機能として商品をカート内に入れたままの状態をキープ
だいたいこの2つです(他にもあると思います)
今回は②のショッピングカート機能を実装したので、そちらを深堀していきます。
#3.セッションの使い方その①〜言葉で説明〜
この項でまず押さえていただきたいのが
「セッション操作は、サーバー(Laravel)内での動作である」
ということを忘れずにお進みください。(この前提が割と大事)
####セッション操作の種類
Laravelでセッションを操作するには主に3つの方法があるようです。
①Requestインスタンス
②Sessionファサード
③Sessionヘルパ
今回は①Requestインスタンスを用いて実装しました。
→今回はショッピングカート機能なので、ユーザーが購入したい商品をカートにいれる際にFormタグで送信(HTTPリクエスト)するため、この方法を用います。
つまり
商品情報を含んだHTTPリクエストを受け取って、その情報をそのままサーバー(Laravel)にセッション情報として保存したい時に有用です。
####大まかな流れ
大きな流れとしては以下のようになります。
やりたいことは非常に簡単です。
①飛んできたRequestをLaravelのセッションへ保存する
②保存したセッション情報を取得し、表示させる
この2つの動作をLaravel上で実装できればOKです。
やることはこの2つだけなのですが、ここにMVCや変数の受け渡しが絡んでくるためややこしいのだと思います...
次に実際に使用するコードについて見ていきます。
#4.セッションの使い方その②〜コードで説明〜
####使用するコード
//セッションに「キー」という名前をつけて、セッション情報を保存します
$request->session()->put('ここにキーが入る', $ここに値が入る);
こちらのコードはaddCartアクション(名前は適当)に記載します。
つまりカートに商品をいれると言う動作を担うアクションに記載します。
このコードにより、サーバー(Laravel)にセッション情報が「キー」と言う名前で保存されます。
//セッションから「キー」という名前を探して、セッション情報を取得します
$request->session()->get('ここにキーが入る', $ここに値が入る);
こちらのコードはindexアクション(名前は適当)に記載します。
つまりカート内商品一覧を表示させる動作を担うアクションに記載します。
このコードにより、サーバ(Laravel)に保存していた「キー」と言う名前のセッション情報を引っ張り出します。
上記2つのコードを使用します
####セッション情報の保存場所について
ちなみに
「セッション情報を保存する」とありますが、
いったいどこにどんな形で保存されるのか?
ここに保存されます↓↓↓
strage > framework > sessions
その中身であるsession情報は以下の通り暗号化?されています↓
a:4:{s:6:"_token";s:40:"uK79rCecgKQ1OItE1PtKdwj5OgPQUX1DbS5tY9FS";s:9:"_previous";a:1:{s:3:"url";s:39:"http://192.168.33.11/●●●●●●●●●●●●●●●";}s:6:"_flash";a:2:{s:3:"old";a:0:{}s:3:"new";a:0:{}}s:3:"url";a:1:{s:8:"intended";s:25:"http://192.168.33.11/●●●●●●";}}
このように、セッション情報は一種の個人情報であるため、暗号化されてサーバー側に保存されています。
#5.カート機能を実装してみる
では、いよいよ実装に入ります。
###ルーティング
Route::resource('cartitem', 'CartController', ['only' => ['index']]);
Route::group(["prefix" => 'iteminfo'], function() {
Route::get('/{id}', 'CartController@show');
Route::post('/add', 'CartController@addCart')->name('addcart');
});
参考までに載せておきます。
###コントローラ
public function show($id)
{
//変数の初期化
$ProductInfo = array();
$ProductCategory = array();
$UserId = '';
//urlパラメータから飛んできたユーザidを元にモデルからそれぞれ商品、カテゴリーを特定
$ProductInfo = Product::findOrFail($id);
$ProductCategory = Category::findOrFail($ProductInfo -> category_id);
$UserId = Auth::user()->id;
return view('iteminfo',
[
'ProductInfo' => $ProductInfo,
'ProductCategory' => $ProductCategory,
'UserId' => $UserId,
]);
}
showアクションはiteminfo画面(商品の詳細画面)を表示させるアクションです
参考までに載せておきます。
###View(商品詳細画面) の Form部分
{!! Form::open(['route' => 'addcart']) !!}
{{ Form::hidden('user_id', $userId) }}
{{ Form::hidden('productId', $productInfo->id) }}
<div class="form-group row justify-content-center">
<label class="col-form-label">購入個数</label>
<div class="">
<input type="number"
class="inputNumber form-control" value="0" name="quantity" >
</div>
<lavel class="col-form-label">個</lavel>
<div class="col-sm-auto">
{!! Form::submit('カートへ', ['class' => 'btn btn-primary']) !!}
</div>
</div>
{!! Form::close() !!}
####解説
これはForm部分で 「カートへ入れる」のボタンの部分になります。
このボタンを押すと下記の動作がに入ります。
①{{ Form::hidden('user_id', $UserId) }}
②{{ Form::hidden('ProductId', $ProductInfo->id) }}
③<input 略 name="Quantity" >
この3つのname属性で送信する(Formで指定したaddCartという名前のルーティングへ)
↓
web.phpを介して、CartController(addCartアクション)へいきます。
###コントローラ(addCartアクション)
public function addCart(Request $request)
{
//セッションに保存したい変数を定義する(ここでは商品idと注文個数)
//飛んできた$requestの中のname属性をそれぞれ指定
$SessionProductId = $request->ProductId;
$SessionProductQuantity = $request->Quantity;
//配列の入れ物を作る(初期化)
$SessionData = array();
//作った配列に、compact関数を用いてidと個数の変数をまとめる(”” を使っているが変数の意味)
$SessionData = compact("SessionProductId", "SessionProductQuantity");
//session_dataというキーで、$SessionDataをセッションに登録
$request->session()->push('session_data', $SessionData);
return redirect('cartitem');
}
####解説
今回セッションに保存したい内容は
①注文された商品のid
②注文された個数
の2つになります。
なので
このアクションでセッションにIDと個数を保存します。
変数を定義して、 ProductId というname属性で飛んできた内容を$requestから抽出します。
$SessionProductId = $request->ProductId;
同じく Quantity というname属性で飛んできた内容を$requestから抽出します。
$SessionProductQuantity = $request->Quantity;
ここで新たな変数を定義し、空の配列を用意してあげます。
※ショッピングカート機能であれば、商品idと注文個数が1セットであって欲しいために新たな変数を定義し、ショッピングはたくさんの商品を買うので、データを管理しやすくするために配列を作成しました。
$SessionData = array();
作成した配列に2つの変数を統合します。
$SessionData = compact("SessionProductId", "SessionProductQuantity");
※この時ダブルクォーテーションがついているが"SessionProductId"は変数を意味しています。
セッションにpushして配列に次々と値を加えていく形をとる
$request->session()->push('session_data', $SessionData);
※大項目4にて、セッションに保存は”put”を用いていましたが、今回は配列に入れていくので”push”となります。
web.phpのcartitemにリダイレクトする
↓
CartControllerのindexアクションに繋がる
(このindexアクションでカート内商品一覧を表示させる動作を担います)
###コントローラ(indexアクション)
public function index(Request $request)
{
//セッションに保存していた値を取得し、変数として定義
$SessionData = $request->session()->get('session_data');
//セッションデータのなかのそれぞれのデータを抽出
$SessionProductId = array_column($SessionData, 'SessionProductId');
$SessionProductQuantity = array_column($SessionData, 'SessionProductQuantity');
dd($SessionData);
}
####解説
セッションに保存していた値を取得し、変数で再定義します。
$SessionData = $request->session()->get('session_data');
array_column関数を用いてIDのデータをそれぞれ抽出し、これもまた変数で再定義します。
$SessionProductId = array_column($SessionData, 'SessionProductId');
注文個数(Quantity)のデータに関しても同様に。
$SessionProductQuantity = array_column($SessionData, 'SessionProductQuantity');
さて、ここで
dd($SessionData);
を記述すれば、ここにどのようなデータが飛んできているのかがわかります。
せっかくなので見ておきましょう。
#6.セッションから取り出したデータ内容を確認
以下は商品詳細画面です。
ここに個数「5個」を入力して「カートへ」ボタンを押すとどうなるでしょう。
ちなみにこのサンプルデータのidは「2」です。
ボタンを押すと
配列でデータが飛んできているのがわかります。
その配列の中にidと個数の情報がはいっているのがわかります。
ではこのあと、他の商品画面に遷移してもう一つ商品をカートに入れてみるとどうでしょう。
商品idは「4」、個数は「8」個でカートに入れてみます。
ボタンを押すと
配列の中に配列でデータが増えて飛んできているのがわかります。
つまり、商品1つにつき、1つの配列でまとめてデータを送信しているということです。
さらに、先ほどカートへ入れた商品データの配列もそのまま残っていることがわかります。
つまり、セッションに保存された内容は、一度画面遷移を行っても情報は保持されたままということです。
そして
この取り出したデータ(変数)を元に、View(カート内商品一覧)でforeach文などを用いて商品データを表示させることができれば、カート機能の完成です!!
#7.まとめ
今回はカート機能についてまとめてみました。
コントローラの使い方や変数の渡し方がすごく重要だと思います。
そして、これがセッションの全てではありませんが、非常に便利な機能だと感じました。
まだまだこれからも精進いたします!
少し長くなってしまいましたが、最後まで読んでいただいた方々、本当にありがとうございますm(__)m