dポイントプレゼントキャンペーン実施中!

・「クラスプロパティ」 へ保存するか、「セッション」へ保存するか迷っています
・両者の寿命の差はどうなっているでしょうか?
・特に「クラスプロパティ」の方を知りたいです
・そのクラスが読み込まれ続けている限りは、「プロパティ」へ保存したデータは読み込み可能?
・あるいは、生成したインスタンスが破棄されない限りは、「プロパティ」へ保存したデータは読み込み可能?
・もしくは、画面を更新しない限りは、「プロパティ」へ保存したデータは読み込み可能?

・利用は、AJAXで画面遷移なしで進んでいく場面間のデータ保持を想定しています

・また、例えば複数人が同時にアクセスして同じ処理が走った場合、「クラスプロパティ」の値は個別保存されるのでしょうか?
・「クラスプロパティ」ではなく「インスタンスプロパティ」だったら、複数保存OK?

A 回答 (4件)

ちょっと難しく書きすぎた気がするのでまとめます。




【ユーザー間で変数の内容が共有されることはないのか?】

「ユーザー」が実行させるのは「プロセス」なので、以下はこの言葉に置き換えます。プロセス間通信という特別な手段を用いない限り、用意されるメモリ領域はまったく別個のものになるので、そのようなことはあり得ません。


【次回実行するまで変数の値は保存されているのか?】

コンピュータにおける「メモリ(主記憶)」と「ハードディスク」の役割の違いは分かりますよね・・・?メモリは一時的な記憶であり、ハードディスクは恒久的な記憶です。ハードディスク上でプログラムを実行することはできず、ハードディスク上に保存されているPHPのソースコードをもとにメモリ上でプログラムが動作します。実行が終わると使われたメモリ領域は全て解放されます。つまり実行中に明示的にハードディスク上にファイルデータとして保存しない限り、情報は消滅します。但し、 $_SESSION に関してだけは、PHP側で保存と復元の作業を自動的にユーザーごと(セッションID)ごとに行ってくれます。


【JavaのGCはPHPにも当てはまるのか?】

[PHPはこちらに該当] Wikipedia - 参照カウント
http://ja.wikipedia.org/wiki/%E5%8F%82%E7%85%A7% …

[Javaはこちらに該当] Wikipedia - マーク・アンド・スイープ
http://ja.wikipedia.org/wiki/%E3%83%9E%E3%83%BC% …

方式は異なりますが、どちらもガベージコレクションは実装されています。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をスカラー値と考えれば、他のスカラー値の扱いと全く同じになります。
    • good
    • 0
この回答へのお礼

「回答」&「リンク提示」&「大変詳しい解説」ありがとうございました。

>zval構造体
・名前を聞いたことはあったのですが、以前調べた際は検索しても全く情報にたどり着けなかった覚えがあります

>C言語
・PHPの深い挙動を解説したページが見つからないのはどうしてだろうと以前から疑問に思っていたのですが、回答を拝見して納得しました
・突き詰めて考えていくと、普段PHPでは気にすることのないメモリの話に踏み込まざるを得なくなるわけですね


・No.2の回答いただいた時点で質問自体は解決したのですが、この辺り以前から疑問に思っていたこともあり、ついでに質問しました
・大変参考になりましたー

お礼日時:2014/01/19 09:46

>> ・逆に言うと、次回、実行するまでは保存されているのでしょうか?



違います。

>> ・インスタンスプロパティに格納した値の寿命がどの段階で尽きるか知りたいです

「インスタンスプロパティに格納した値の寿命」というよりは「インスタンスの寿命」として考えるべきでしょう。プロパティだけが消滅してインスタンス自体が生きていることはプログラミング言語の構造上絶対にあり得ません。これが疑問に感じるならば「インスタンス」という言葉の意味を取り違えています。

以下では、オブジェクトのインスタンスに限らずPHPのあらゆる変数・値について広義に説明します。C言語レベルで見れば、PHPのあらゆる変数はzval構造体であり、PHP言語で言うオブジェクトのようなものであるからです。

・実行中のプロセスがメモリ上で稼働している最中である
・そのzval構造体の参照カウントがゼロより大きい
・セマフォや共有メモリなど特殊なプロセス間通信の手段を用いていない

上記全てを満たす間、メモリ上にzval構造体のデータは存在し続けます。参照カウントに関しては下記を参考にどうぞ。

参照カウント法の原理
http://www.php.net/manual/ja/features.gc.refcoun …

根本的に理解しようとすると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言語レベルにおける「オブジェクト」そのものを指します。リンク先では省略されていますが、「プロパティのシンボルテーブル構造体」「メソッドのシンボルテーブル構造体」などを保持するものと思えばいいでしょう。
    • good
    • 0
この回答へのお礼

回答ありがとうございました。

>PHPのデータ構造
・このリンク先の図、凄いですね
・しかも2009年時点で公開……、(初めて見ました……)

>分かりやすく説明するのであれば下記のようになるでしょう
・一番知りたいのは「PHPではどうなの?」て部分だったので、「PHP言語レベルにおける~」と丁寧に用語解説いただいた点が嬉しかったです

・大変参考になりましたー

お礼日時:2014/01/19 10:01

えーっと、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

この回答への補足

回答ありがとうございました。

>えーっと、PHPでいいんですよね
・書いていませんでしたが言語はPHPです

>次回の実行時には初期値に戻っています
・逆に言うと、次回、実行するまでは保存されているのでしょうか?
・インスタンスプロパティに格納した値の寿命がどの段階で尽きるか知りたいです
(参照できなくなるのはいつ?)

・1さんが提示いただいたリンク先に下記記述があるのですが、これはPHPにも当てはまるのでしょうか?
>スコープから外れると、オブジェクト変数は無くなり(メモリから破棄)オブジェクトへの参照が無くなります。ところが、オブジェクトはこの段階では無くなりません
>Javaの特徴であるガベージコレクション(garbage collection)という機能が働きます

・「オブジェクト変数が無くなる」と「オブジェクトが無くなる」は、また別の話なのでしょうか?

補足日時:2014/01/02 09:21
    • good
    • 0

おそらく言語はJavaだと思いますが。


オブジェクト変数の寿命はスコープの範囲内です。(URLのオブジェクトの寿命を参考にしてください。)

なのでセッションに保持しないのであれば、インスタンスは持ち回る必要があります。
また複数人がアクセスした場合は、どのような作りをされるのかわかりませんが通常はその分だけインスタンスが生成されるので問題ないです。

参考URL:http://lecture.ecc.u-tokyo.ac.jp/~cmich/javabook …

この回答への補足

回答ありがとうございました。

>おそらく言語はJavaだと思いますが
・書いていませんでしたが言語はPHPです

補足日時:2014/01/02 09:08
    • good
    • 0

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!