ガンズターン 公式サイト

楽しいことに、まじめです。 ——ガンズターンアプリ研究所公式サイト

FuelPHPでSessionクラスを使ってみた話

Pocket

はじめての豚丼

今日は、夕飯に豚丼を自分で作って食べてみました。
醤油、みりん、お酒でたれを作って、塩胡椒で炒めた玉ねぎと豚肉にかけて煮ること5分ぐらい。
実にやさしいお味になって、お腹も心も満足しています。

そのせいか分かりませんが、お風呂上りに体重計に乗ったら体内年齢が実年齢+6歳にまで跳ね上がっておりました。

……これはやばい。早くなんとかしないと。(汗)

ところで昨日の記事を改めて読み返してみましたが、相当やばいですね。
我ながら、自分の脳みそが心配です。
悪ノリもほどほどにしないと、後々自分が後悔しそうなので気をつけます。

はい。前置き長いのももはや恒例ですね。

こんばんは。ガンズターンのRyosukeです。

今日は、FuelPHPのSessionクラスをはじめて使ってみて、その便利さに感動したのでそれに関するお話をば。
実装途中でハマってしまった問題の解決方法も書きましたので、どなたかのご参考になれば幸いです。
逆に言うとプログラミングまったく興味ない人には意味不明な文章かも……。
その時はざぁっと真ん中飛ばして、最後の段落だけでも読んでくださるとうれしいです。

1. FuelPHP理解したぜぇっ、と調子に乗っていた話。

以前も書きましたが、わたし、サーバ側のプログラミングはまったくもってど素人です。
これまで、趣味ですらサーバに触ったことはありません。
ですので、現在、必要に迫られて、必死こいて勉強している最中なんですが……。

それでもサーバ独特の考え方でプログラミングしなきゃいけない時なんかは、ちょっとしたことでつまずいて、自信喪失してしまうことが多いです。

今日なんか、まさにその典型ですね。
ある程度FuelPHPにも慣れてきて、MVCモデルの中でどんな風にデータが流れていくのかが体感的にわかってきたところだったんで、油断していました。

ちょっと色気を出して、管理画面を自作しようと思ったのが発端です。
もちろん「oil g admin」で簡単に作成できるスキャフォールディングを土台にして、の話ですが。

MVCモデル、すでにご存知の方には釈迦に説法だと思いますので詳しい説明は避けますが、要は「内部処理を担当する部分(Model)」と「入力と出力を担当する部分(View)」、そして「それらの仲立ちをする部分(Controller)」の3つに分けてプログラミングをしていこう、という考え方です。(←あくまで「わたしはそう理解してる」程度の意味です)

FuelPHPもこのMVCモデルに則って構成されてるんですが、大まかに言うとクラスが3種類あるんですね。
ずばり「Modelクラス」、「Viewクラス」(正確にはViewはクラスじゃないのですが、わかりやすくここではクラスとしておきます)、「Controllerクラス」の3つです。

んで、FuelPHPのプログラミングをしていくってことはつまり、この3種類のクラスを縦横無尽に駆けずり回ってあっちこっちに少しずつコードを付け足しながら1つの機能を実装していくってことになるんです。

……大変そうだと思いますか?

まあ、確かに最初は大変です。
単純に考えて、1つの機能を実装するのに最低3箇所は手を加えないといけないわけですからね。

けれど、面食らうのも最初だけです。
ちょっと真面目に勉強すればすぐに慣れてしまいます。

そしてだんだんと、MVCモデルの考え方に自分の思考回路が順応してきて、
「こういう機能を実装したいんなら、こことここをこんな風にいじればOKだな」
とかっていうのがすぐ分かるようになってきます。

そうなってくると、どんどんFuelPHPでプログラミングするのが楽しくなってくるわけですが……。

ちょうどそんな状態にわたしが到達していた本日未明、悲劇は起こりました。
この悲劇により、伸びに伸びきっていたわたしの天狗の鼻は、今やぽっきりと根元から折られてしまったのでした……

2. FuelPHPにおける単純化したMVCの流れ

えっと、ちょっとここから本格的に込み入った話になってきます。
このブログを現在読まれている主な方々(Ryosukeの脳内想定です)はあまりプログラミングに詳しくない方が大半だと思いますので、無理して読まれると体に毒かも知れません。

はい。
そんなわけで、ここから先はこれまで以上に説明文抜きで話を進めることについて予防線を張っておきますね。ごめんなさい。m(_ _)m

さて、MVCモデルでは、Model、View、Controllerの3種類のクラスを処理とデータが行ったり来たりするということは先に述べた通りです。

とくにFuelPHPのWeb画面作成における流れは、だいたい以下のようになります。

①入力されたURIを元に、担当するControllerクラスが特定される
②Controllerクラスがなんらかの処理をして、Viewクラスを呼び出す
③ViewクラスがControllerクラスから受け取ったデータを元にHTMLを生成
④ブラウザがHTMLを認識してWebページの表示を行う

(え? Modelクラスがどこにもないじゃないかって?
 そうですね。おっしゃる通りです。
 Modelクラスについては、一連の流れの中で必ず登場してくるわけではありません。
 ②の中で、必要に応じてControllerクラスから呼び出されるわけです。
 なので、簡略化のためここではあえて抜いて書きました。)
 

3. ControllerからViewへのデータ渡しは簡単です。

ControllerクラスからViewクラスへデータを渡すことは比較的容易です。
具体的に書くと、Controller側の②の手順の最後で、

$data['hoge'] = 'fuga';
$this->template->content = View::forge('foo/some/view', $data);

という風に、Viewクラス生成メソッド(forge)の第2引数に、そのまんまデータを突っ込んであげればいいだけです。
こうすることによって、View側で、

echo $hoge;

としてやれば、画面に表示される文字列は「fuga」となるわけです。(ここで、View側で渡されたデータを参照するときは$dataではなく、そのkey値であるところの’hoge’が変数名になっていることに注意)

さて。

ここまではわたしも以前から理解できていたんですが、いざ自分でプログラミングしていると、データの流れはController→Viewだけでは足りないことに気づきました。

4. ViewからControllerにデータを渡す流れも必要だよ

見出しの通りですね。
どうしても、View側ではじめて特定されるデータ(例えばユーザの選択結果など)、あるいは別のControllerクラスで使用していたデータなどを、Controller側に渡してやる必要が出てくるのです。

通常、この流れはさほど難しくなく実装できます。

というのも、HTMLでごく一般的に用いられているForm要素を使えば、解決できるからです。
Formのaction属性にデータを渡してあげたいControllerクラス(およびそのメソッド)を示すURIを指定してあげて、さらにそのForm内で、渡したいデータをhidden要素などにしてあげればOKです。

だからわたしも、単純にその通りに実装してみました。

すると……

5. 「Array to string conversion」になりました。

はい。エラーメッセージが出て処理が先に進まなくなっちゃったんですね。
以下に、FuelPHPから出力されたエラーメッセージをそのまま引用しますね。

Fuel\Core\PhpErrorException [ Notice ]:
Array to string conversion

直訳すると「配列から文字列への変換」ってことになりますが、最初に見たときは意味わかりませんでした。

「配列から文字列へ変換なんてする気はさらさらないぞ! なんでこんなメッセージが出るんだ!? FuelPHPのバグじゃないのか!?」

……そんなわけありませんでした。

単純に、わたしがFuelPHPのことをわかっていた気になっていただけで、その使い方を間違っていただけなんですね。
このことにわたしがどれほどのショックを覚えたかというと……

むりやり人間関係に例えて言うなら、ずっと両思いで付き合ってると思い込んで何回もデートしたはずの相手に、実は「ただのお友達の一人」と思われていたことが発覚した、そのうえデートだと思っていたのは向こうからしたらただの暇つぶしだった、ぐらいのショックでしょうか。

いや、全然ちがうな。……まあいいや(笑)

話を先に進めましょう。

6. Controllerへは、文字列データしか渡せない?

はい。どうやらそのようなんですね。
考えてみれば、postで渡そうがgetで渡そうが、HTTPの枠組みの中でやり取りするわけなので、文字列しか渡せないのは当たり前ですね。
けれど、なまじViewへのデータ渡しが簡単にできていたので、Controllerも同じだろうという思い込みがあり、そこに気づくまでに2時間ぐらい悩んでしまいました。

つまり文字列しか渡せないところへ、わたしときたら連想配列をなんの変換もせずにそのままぶち込んでいたわけです。
そりゃ、エラーも出ますわな。

んじゃあ、どうやって解決したらいいんじゃい、てことで色々とネットサーフィンしてヒントを探すわけですが……。

7. どうやらSessionが便利らしい?

ようやく出ました。Sessionクラス。
恥ずかしながら、わたしセッション(Session)について真面目に考えたのは今日が初めてだったりします。

これまでも何度かセッションという言葉を耳にしたことはありますが、なんだか難しい世界の話のようで、自分には無縁の単語なんじゃないかと思っていたので……。
無意識に調べることを避けていたんですね。

けれどSession、わかってしまえばこれほど便利で、簡単な仕組みがあるでしょうか。いや、ない。(反語)

しかもFuelPHPにはセッションをより簡単に使うためのSessionクラスがあるので、基本さえ知ってしまえば誰にでもすぐ扱えるようになります。

8. Session使うとなにが便利なの?

ずばり「Controllerに配列でもオブジェクトでもなんでもそのまま渡せる」ようになります。

そもそもセッションは、複数のユーザーが同時にWebページなどを閲覧している時、個々のユーザーの状況を個別に管理するための仕組みです。(←またしてもわたしの勝手な理解かも、ですが)

ユーザーは星の数ほどいても、稼働しているサーバは1個ですからね。
1個のサーバが、同時並行的にユーザー別の処理をして、みんなが同時にWebページにアクセスしても変なことにならないように工夫してあげる必要があります。

その工夫の1つが「セッション」です。

セッションを使うと、各ユーザーごとにセッションIDが割り振られます。
さらにそのセッションIDに、今、それぞれのユーザーの処理がどこまで進んでいるのかが紐付けられて保存されます。

そうすることによって、ユーザーからリクエストが来た瞬間に、サーバが適切な処理を判断して、複数のユーザーそれぞれに対して矛盾のない状況を作り出しているわけです。

さて、この「セッションIDにそれぞれのユーザーの状況を紐付ける」という仕組みがミソです。

これ、言い換えれば「セッションIDで示される場所に、好きな名前で好きなデータを保存しておける」ってことになるんです。

9. 具体的には?

FuelPHPの具体的な例で見ていきましょう。

まず、値を保存したい場合はこうです。

// 値の保存
$set_value = array('foo' => 'bar', 'baz' => 'qux');
Session::set('hogehoge', $set_value);

それから、保存した値を取り出したい場合はこう。

// 値の呼び出し
$get_value = Session::get('hogehoge');

はい。これだけ。
こんな単純でわかりやすいコードを、Controllerが呼び出される前後で行ってあげればよいだけです。

実に簡単ですね。
わたしもさっそく実装してみました。

……すると……

10. 何度やってもgetした値がnullなんだが。

……何一つ、うまく行きませんでした! orz……

この答えにたどり着くまでに貴重な一日の半分を使ったというのに……!

しかし、わたしはあきらめませんでした。
もうちょっとで、解決できそうな感触があったのです。

なんとなく「Sessionクラス周りの設定が怪しそうだ」と目星をつけたわたしは、またしてもGoogle先生に助けられます。

なんと、Sessionクラスのデフォルトの設定では、4kbまでの情報しかセッションに保存できないということがわかったのです。
(この縛り、FuelPHPの仕様というよりCookieの仕様のようですね)

それがわかったらあとは解決まであっという間でした。

11. セッション情報の保存先をfileにする

FuelPHPの「fuel/core/config/session.php」を「app/config/session.php」にコピーして、以下の部分を書き換えます。

'driver'            => 'cookie', //←ここ(cookieの部分)を、

                ↓

'driver'            => 'file', //←こう(fileに)書き換える。

こうすることで、セッション情報の保存先が「cookie」から「file」になり、容量4kbまでの制限はなくなります。

12. ようやく問題解決!!

うむむ。
技術の話題って、どこまで詳しく書くかで文章量がぐっと変わりますね……(^_^;)
今回は、わたし自身がなにをどのように勘違いしていたのかも含めて、おさらいのつもりでできるだけ詳しく書いたつもりです。
しかしその結果、たった1個の問題解決のために6000文字強も費やしてしまいました。

要した時間はなんと3時間……!

完全に本業に支障が出ている……(汗)

とはいえ、この長い記事が世界中のどなたかたった一人にでもいいので、いつか何かのお役にたつことがあるのなら悔いはありません。

本日は最初から最後まで真面目に書いてみました。
かなり疲れたので、もう寝ようと思います。

それではまた明日。
朝食に食べる予定の豚丼の残り物が非常に楽しみな、Ryosukeでした!m(_ _)m

Pocket

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

トラックバックURL: http://gunsturn.com/2015/05/09/fuelphp_use_session/trackback/