クラスプロパティとセッションの保存について

このQ&Aのポイント
  • クラスプロパティとセッションの保存方法について迷っています。特にクラスプロパティの寿命について知りたいです。
  • クラスが読み込まれ続けている限り、クラスプロパティへ保存したデータは読み込み可能です。また、生成したインスタンスが破棄されない限りも同様です。
  • 画面を更新しない限りは、クラスプロパティへ保存したデータは読み込み可能です。AJAXを使用した画面遷移なしでのデータ保持に適しています。
回答を見る
  • ベストアンサー

「クラスプロパティ」 or 「セッション」保存?

・「クラスプロパティ」 へ保存するか、「セッション」へ保存するか迷っています ・両者の寿命の差はどうなっているでしょうか? ・特に「クラスプロパティ」の方を知りたいです ・そのクラスが読み込まれ続けている限りは、「プロパティ」へ保存したデータは読み込み可能? ・あるいは、生成したインスタンスが破棄されない限りは、「プロパティ」へ保存したデータは読み込み可能? ・もしくは、画面を更新しない限りは、「プロパティ」へ保存したデータは読み込み可能? ・利用は、AJAXで画面遷移なしで進んでいく場面間のデータ保持を想定しています ・また、例えば複数人が同時にアクセスして同じ処理が走った場合、「クラスプロパティ」の値は個別保存されるのでしょうか? ・「クラスプロパティ」ではなく「インスタンスプロパティ」だったら、複数保存OK?

  • re97
  • お礼率80% (601/744)
  • PHP
  • 回答数4
  • ありがとう数13

質問者が選んだベストアンサー

  • ベストアンサー
noname#244856
noname#244856
回答No.4

ちょっと難しく書きすぎた気がするのでまとめます。 【ユーザー間で変数の内容が共有されることはないのか?】 「ユーザー」が実行させるのは「プロセス」なので、以下はこの言葉に置き換えます。プロセス間通信という特別な手段を用いない限り、用意されるメモリ領域はまったく別個のものになるので、そのようなことはあり得ません。 【次回実行するまで変数の値は保存されているのか?】 コンピュータにおける「メモリ(主記憶)」と「ハードディスク」の役割の違いは分かりますよね・・・?メモリは一時的な記憶であり、ハードディスクは恒久的な記憶です。ハードディスク上でプログラムを実行することはできず、ハードディスク上に保存されているPHPのソースコードをもとにメモリ上でプログラムが動作します。実行が終わると使われたメモリ領域は全て解放されます。つまり実行中に明示的にハードディスク上にファイルデータとして保存しない限り、情報は消滅します。但し、 $_SESSION に関してだけは、PHP側で保存と復元の作業を自動的にユーザーごと(セッションID)ごとに行ってくれます。 【JavaのGCはPHPにも当てはまるのか?】 [PHPはこちらに該当] Wikipedia - 参照カウント http://ja.wikipedia.org/wiki/%E5%8F%82%E7%85%A7%E3%82%AB%E3%82%A6%E3%83%B3%E3%83%88 [Javaはこちらに該当] Wikipedia - マーク・アンド・スイープ http://ja.wikipedia.org/wiki/%E3%83%9E%E3%83%BC%E3%82%AF%E3%83%BB%E3%82%A2%E3%83%B3%E3%83%89%E3%83%BB%E3%82%B9%E3%82%A4%E3%83%BC%E3%83%97 方式は異なりますが、どちらもガベージコレクションは実装されています。C言語のようにfree関数を使って動的なメモリ解放をしたりする必要がないということです。もちろんPHPはC言語ベースで成り立っており、内部的にはfree関数によってメモリ解放が行われてはいるのですが。 【「オブジェクト変数が無くなる」と「オブジェクトが無くなる」の違いは?】 それぞれは別個の事柄ですが、refcountが1であるケースについてはこれらは同時に発生します。refcountが2以上であるケースでは前者しか発生しません。別の変数がまだそのオブジェクトを利用しているからです。 また、オブジェクトの参照に関しては少しややこしいので、まず私の知恵ノートをお読みください。 http://note.chiebukuro.yahoo.co.jp/detail/n127275 例を挙げます。 1. $a = new stdClass; 2. $a->hoge = 'test'; 3. $b = $a; 4. $c = &$a; 5. $a = null; これを実行すると、$aと$cはNULL、$bはプロパティ「hoge='test'」を持つstdClassオブジェクトとなります。オブジェクトIDを用いて説明すると、下記のようになります。 1. zend_object_value構造体(stdClass)が生成され、ID(#1)が割り振られる。そしてID(#1)がzval構造体($a)に対応するzvalue_value共用体にセットされる。 zval($a, refcount = 1, is_ref = 0) … zvalue_value(#1) 2. zend_object_value構造体(stdClass)のハッシュテーブルに「hoge='test'」がセットされる。実際にはこれもzval構造体($hoge)→zvalue_value共用体('test')→str構造体のようになっているがここでは大雑把に考える。 zval($a, refcount = 1, is_ref = 0) … zvalue_value(#1) 3. zval構造体($b)がzval構造体($a)と同じzvalue_value共用体を指すようにする。 zval($a, refcount = 2, is_ref = 0) … zvalue_value(#1) zval($b, refcount = 2, is_ref = 0) … zvalue_value(#1) 4. zval構造体($c)がzval構造体($a)と同じzvalue_value共用体を指すようにする。 zval($a, refcount = 3, is_ref = 1) … zvalue_value(#1) zval($b, refcount = 3, is_ref = 0) … zvalue_value(#1) zval($c, refcount = 3, is_ref = 1) … zvalue_value(#1) 5. zval構造体($a)とzval構造体($c)が指すものとして、新しくNULL構造体(?)をセットしたzvalue_value共用体が用意される。 zval($a, refcount = 2, is_ref = 1) … zvalue_value(NULL) zval($b, refcount = 1, is_ref = 0) … zvalue_value(#1) zval($c, refcount = 2, is_ref = 1) … zvalue_value(NULL) オブジェクトIDをスカラー値と考えれば、他のスカラー値の扱いと全く同じになります。

re97
質問者

お礼

「回答」&「リンク提示」&「大変詳しい解説」ありがとうございました。 >zval構造体 ・名前を聞いたことはあったのですが、以前調べた際は検索しても全く情報にたどり着けなかった覚えがあります >C言語 ・PHPの深い挙動を解説したページが見つからないのはどうしてだろうと以前から疑問に思っていたのですが、回答を拝見して納得しました ・突き詰めて考えていくと、普段PHPでは気にすることのないメモリの話に踏み込まざるを得なくなるわけですね ・No.2の回答いただいた時点で質問自体は解決したのですが、この辺り以前から疑問に思っていたこともあり、ついでに質問しました ・大変参考になりましたー

その他の回答 (3)

noname#244856
noname#244856
回答No.3

>> ・逆に言うと、次回、実行するまでは保存されているのでしょうか? 違います。 >> ・インスタンスプロパティに格納した値の寿命がどの段階で尽きるか知りたいです 「インスタンスプロパティに格納した値の寿命」というよりは「インスタンスの寿命」として考えるべきでしょう。プロパティだけが消滅してインスタンス自体が生きていることはプログラミング言語の構造上絶対にあり得ません。これが疑問に感じるならば「インスタンス」という言葉の意味を取り違えています。 以下では、オブジェクトのインスタンスに限らずPHPのあらゆる変数・値について広義に説明します。C言語レベルで見れば、PHPのあらゆる変数はzval構造体であり、PHP言語で言うオブジェクトのようなものであるからです。 ・実行中のプロセスがメモリ上で稼働している最中である ・そのzval構造体の参照カウントがゼロより大きい ・セマフォや共有メモリなど特殊なプロセス間通信の手段を用いていない 上記全てを満たす間、メモリ上にzval構造体のデータは存在し続けます。参照カウントに関しては下記を参考にどうぞ。 参照カウント法の原理 http://www.php.net/manual/ja/features.gc.refcounting-basics.php 根本的に理解しようとするとC言語に対する知識が不可欠となります。上記をより分かりやすくした図を描こうと思っていたら既に素晴らしいものが作成されていたのでリンクを掲載します。 PHPのデータ構造 http://d.hatena.ne.jp/yokkuns/20090614/1244994082 【補足】 上記リンク先では「シンボルテーブル」「ハッシュテーブル」と言葉を使い分けていますが、どちらも値の探索速度が O(n) ではなく O(1) であることに着目すると、どちらにもチェインハッシュが使われていると思われるので本質的には同じものと考えていいでしょう。シンボルテーブルに下記のような種類があると考えればいいと思います。 ・グローバル領域 ・名前空間領域 ・配列領域 ・関数領域 ・オブジェクトプロパティ領域 ・オブジェクトメソッド領域 チェインハッシュ法 http://kimama2index.info/algorithm/hash_chain.html また、各構造体・共用体を分かりやすく説明するのであれば下記のようになるでしょう。 [シンボルテーブル構造体] PHP言語レベルの「変数名」や「配列キー名」をC言語レベルの「ハッシュキー」として、C言語レベルのzval構造体(PHP言語レベルの「変数」そのもの)と結びつけるハッシュテーブルです。 [zval構造体] zvalue_value共用体のラッパー構造体です。わざわざこれを用意しなければならないのは、「参照」という概念が存在するから、つまり複数のzval構造体が共通のzvalue_value共用体を指すケースが存在するからです。 [zvalue_value共用体] PHP言語レベルにおける「値」そのものを指します。共用体はメモリ上の1ヵ所に集約されており、PHPのあらゆる値はこれに属するとも言えるでしょう。(NULLを含む)スカラー値に関しては、それぞれ専用の原始的な構造体がセットされます。配列の場合には、次の(配列領域の)シンボルテーブル構造体へのポインタが張られます。オブジェクトの場合には、zend_object_value構造体を識別するID(オブジェクトID)がセットされます。 [str構造体] C言語において「文字列」という型は存在せず、「文字の配列」として実現するしかありません。これはzvalue_value共用体で述べた原始的な構造体の一種です。配列要素のそれぞれの値と配列サイズだけを保持します。これより細かい構造体・共用体に分解することは出来ません。 [zend_object_value構造体] PHP言語レベルにおける「オブジェクト」そのものを指します。リンク先では省略されていますが、「プロパティのシンボルテーブル構造体」「メソッドのシンボルテーブル構造体」などを保持するものと思えばいいでしょう。

re97
質問者

お礼

回答ありがとうございました。 >PHPのデータ構造 ・このリンク先の図、凄いですね ・しかも2009年時点で公開……、(初めて見ました……) >分かりやすく説明するのであれば下記のようになるでしょう ・一番知りたいのは「PHPではどうなの?」て部分だったので、「PHP言語レベルにおける~」と丁寧に用語解説いただいた点が嬉しかったです ・大変参考になりましたー

noname#244856
noname#244856
回答No.2

えーっと、PHPでいいんですよね。 まず、クラスプロパティであろうとインスタンスプロパティであろうと、明示的にファイルに保存しない限りデータは維持されません。次回の実行時には初期値に戻っています。但し、 $_SESSION だけは例外で、session_start() が実行済み且つクッキーでブラウザ側からセッションIDが送られてきているとき、セッションごと(ユーザーごと)に情報が復元されます。 以上を踏まえて質問を読み替えるならば ・バラバラに情報を $_SESSION に保存するか ・インスタンスプロパティに情報をセットしてオブジェクトごと $_SESSION に保存するか こういうことになりますよね。個人的な意見としては、どちらもNGです。 ・ユーザーIDのみをセッションに保存し、アクセス毎に必要な情報をデータベースから情報を引き出す これが理想ですね。但しサイト規模・アクセス頻度が膨大になるとPDO+MySQLだけでは対応できなくなるため、TokyoTyrant関数群を利用するという選択肢も発生してきます。mixiのログイン履歴管理にはこれが使われているそうです。 PDO http://php.net/manual/ja/book.pdo.php PHPでデータベースに接続するときのまとめ http://qiita.com/mpyw/items/b00b72c5c95aac573b71 tokyo_tyrant http://php.net/manual/ja/book.tokyo-tyrant.php

re97
質問者

補足

回答ありがとうございました。 >えーっと、PHPでいいんですよね ・書いていませんでしたが言語はPHPです >次回の実行時には初期値に戻っています ・逆に言うと、次回、実行するまでは保存されているのでしょうか? ・インスタンスプロパティに格納した値の寿命がどの段階で尽きるか知りたいです (参照できなくなるのはいつ?) ・1さんが提示いただいたリンク先に下記記述があるのですが、これはPHPにも当てはまるのでしょうか? >スコープから外れると、オブジェクト変数は無くなり(メモリから破棄)オブジェクトへの参照が無くなります。ところが、オブジェクトはこの段階では無くなりません >Javaの特徴であるガベージコレクション(garbage collection)という機能が働きます ・「オブジェクト変数が無くなる」と「オブジェクトが無くなる」は、また別の話なのでしょうか?

回答No.1

おそらく言語はJavaだと思いますが。 オブジェクト変数の寿命はスコープの範囲内です。(URLのオブジェクトの寿命を参考にしてください。) なのでセッションに保持しないのであれば、インスタンスは持ち回る必要があります。 また複数人がアクセスした場合は、どのような作りをされるのかわかりませんが通常はその分だけインスタンスが生成されるので問題ないです。

参考URL:
http://lecture.ecc.u-tokyo.ac.jp/~cmich/javabook/chap03.htm
re97
質問者

補足

回答ありがとうございました。 >おそらく言語はJavaだと思いますが ・書いていませんでしたが言語はPHPです

関連するQ&A

  • セッションにはどんなデータを保存するべきか

    セッションにどんなデータを保存していいのかよくわかりません。 私はセッションというのはプログラムでいうところのstatic変数みたいな物かと考えているのですが、 この認識であっているでしょうか? 具体的にはセッションにはユーザID等のWebシステム上全体で保持するべき値のみが許されて、A,B,Cの3つの画面間でのみ共有するような値はセッションに保存してはいけないという具合です。 抽象的な質問ですが、よろしければご回答下さい。

  • Weblogicのセッションについて

    Weblogic10.0.3にてWebアプリケーションの 開発を行っていますが、解決しない問題があり 質問させていただきます。 現在、ログイン画面にてユーザーIDとパスワードを 入力してログイン後各処理を行うアプリを開発していますが、 ログイン時のユーザー情報をセッションに保持する作りに していますが、ログイン時にjsessionidがURLに 表示されてしまいます。 (例:http://testserver:9000/TestApp/Test.do;jsessionid=vFqyK3xMrJ9QCLJnW0X0r2w17ylBVhhD2VQT4qGwdMsGvhnZHdJQ!-425034523) 一度ログインするとそのブラウザを閉じるまでは、画面遷移をしても 何度ログイン・ログアウト処理(セッションの生成・削除)を 行っても二度と表示されません。 (画面遷移はStrutsで制御しています) セッションIDをCookieに保持する方法もあるようですが、 なるべくCookieを使いたくないので、セッションに保持するように したいのです。 web.xml、weblogic.xml、Weblogicサーバーの設定などで セッションIDを表示しなくなる方法がありましたら 教えてください。よろしくお願いします。

  • PHP セッションを利用した入力フォーム

    入力内容をセッションで保持しているフォームで, 入力画面から「前の画面に戻る」ボタンが押された際に 保持していた入力内容のセッションを破棄するようにしたいのですが, どのようにしたらいいでしょうか. unset($_SESSION['変数名'])で破棄できるのはわかっているのですが, これをどこに記述したらいいのかがわかりません. それとも,別の破棄する方法があるのでしょうか. 入力内容に関係ないところでもセッションを使っているので, session_destroy()ですべて破棄するのはしたくありません. よろしくお願いいたします.

    • ベストアンサー
    • PHP
  • php+mysqlでデータを表示更新削除するシステムを製作中ですが

    PHP+MYSQLでデータを取り出し、入力変更を行うシステムを製作しているのですが、 取り出したデータを保持してのページ遷移ができません。 どのように行えばよいのでしょうか? 製作中のシステムの条件は以下の通りです。 ・MYSQLから取り出したデータはクラスに保持する。 ・フレームワークは使用しない。 ・セッションは使用しない。 ・直接ページ遷移するのではなくMVCモデルのように 一度コントローラ部のような所に遷移し変更削除の確認画面に遷移する。 入力画面←→コントローラ部←→確認画面 のような感じです ・確認画面から入力画面に戻った時、入力変更した項目は表示する。 以上です。自分で調べた限りではセッションを使用しないと不可能のような気がしますが・・・。

    • 締切済み
    • PHP
  • 特定のセッション変数の内容だけ破棄

    $_SESSION['data1'] $_SESSION['data2'] $_SESSION['data3'] $_SESSION['data4']  このようにセッション変数が複数ある場合、session_destroy();を宣言するとすべてのセッション変数の内容が破棄されますが、例えば「$_SESSION['data1']と$_SESSION['data2']だけ」といったように、特定のセッション変数の内容だけを破棄することは出来ますか?

    • ベストアンサー
    • PHP
  • PHP セッション情報のDBへの受け渡し

    お世話になります。 標題の件について、以下のとおり説明します。 (1)1ページ目:入力フォームで入力した情報をセッションに保持 (主にプルダウンメニューの情報とテキスト) submitボタンで次画面へ ↓ (2)2ページ目:サムネイル写真をクリックした情報を保持+インラインフレームで拡大写真表示 (クリックした情報をプルダウンメニューに表示してセッションへ保持) submitボタンで次画面へ ↓ (3)3ページ目:サムネイル写真をクリックした情報を保持+インラインフレームで拡大写真表示 (クリックした情報をプルダウンメニューに表示してセッションへ保持) submitボタンで次画面へ ↓ (4)4ページ目:上記内容の確認画面 submitボタンで次画面へ ↓ (5)送信 現状、上記の流れでセッション情報を保持しつつメールでの送信が確認出来ています。 ですが、ページ遷移で確認画面から前画面へ戻って、例えば2ページ目の写真を変更して、submitで次画面へ遷移すると、3ページ目の情報がなくなり新たに写真を選択する必要になってしまいます。 なので、ページを前後遷移しても情報が保持された状態にするには、どうすれば良いでしょうか? データベースを使わないと出来ないことでしょうか? データベースに関しても勉強しておりますが、セッション情報をDBへ登録して、その後ページを遷移した場合に、データベースから呼び出すようなイメージなのでしょうが、それにはどうすれば良いのかが不明です。 お手数ですが、ご教授の程、よろしくお願いします。

    • ベストアンサー
    • PHP
  • Ajaxにおけるセッション

    会社の先輩から 「Ajaxを使ったWebページはセッション(※セッションIDのことを短縮して言ったのかは不明)を持ち続けてしまうことが問題」 と言われたのですが、これは正しいのでしょうか? XMLHttpRequestのオブジェクトから常にopen、sendし続けているのであれば セッションを持ち続けるかもしれませんが、 例えばopen、sendをページのロード時にたった一回しかつかわないページであれば、 最初のreadystateの値が4になった時点で(もう二度とXMLHttpRequestのオブジェクトからはリクエストしないので)コネクションは切れて 放っておくとセッションIDは切れるのではないでしょうか? それともクライアント(ブラウザ)にXMLHttpRequestのオブジェクトが存在している限り、 セッションは切れずに保持されるのでしょうか? よろしくお願いします。

  • 同一セッションIDのブラウザを複数開かせたくない

    ASP、ActiveXDLL、JavaScriptで作られているシステムのメンテナンスをしています。 DBはOracle9iです。 一部の大変複雑な処理をしているところや、画面遷移時に仮保存状態として処理するためにASPプログラム内でワークテーブルを作成し、そこに保存しております。 ワークテーブルは「IPアドレス+セッションID+元テーブル名」としており、IEで ・「Shiftキー+リンククリック」 ・「Ctrl+N」 ・「リンクを新しいウィンドウで開く」 などで、同一セッションIDでブラウザを複数画面操作できるので、その複数画面で同じプログラムで操作すると同じワークテーブルを扱い、おかしなデータができてしまいます。 多数のプログラムでワークテーブルを使用しており、ワークテーブルの名前を変更することは時間的に無理があるので、同一セッションで複数画面を開かせないようにしたいと思っているのですが、なんとか実現できませんでしょうか? よろしくお願いします

  • rubyのクラス変数のようなものは無い?

    rubyのクラス変数に相当するものはPHPにはないのでしょうか? つまり、あるクラスの全てのインスタンスで共有する変数です。 DB中に存在する環境固有の値をクラスで保持したいのですが、インスタンスごとにDBアクセスするのは無駄なので、初回インスタンス生成時(is_nullで判断)にのみDBアクセスして、あとはそれを参照するだけにしたい。 globalを使って全体でのグローバル変数にするしかないのでしょうか?

    • ベストアンサー
    • PHP
  • マルチスレッド下でのインスタンス変数・クラス変数

    よろしくお願いします。  マルチスレッド下で動作するクラスを作成しています。データにアクセスするためのオブジェクトを クラスのフィールド値として保持し、使い回しを行いたいと考えています。このデータアクセスオブジェクト(以下Dao)内では特にフィールドは使用せず、全てローカル変数のみで動作するようになっています。Dao自体は初回のクラス生成時にstatic処理にてフィールドにセットされます。  このDaoを保持するフィールドは、staticなクラス変数が良いのか、インスタンス変数として保持する方が良いのか迷っております。  クラス変数ならばPermanent領域をオブジェクト1つ分のメモリ使用で済み、インスタンス変数だとスレッド毎にheapを使い、処理数が増えるとメモリ圧迫しちゃう?と安易に考えてしまったりしています。  ご意見・ご助言よろしくお願い致します。

    • ベストアンサー
    • Java

専門家に質問してみよう