192

$ _SESSIONに実際にオブジェクトを格納できることがわかりました。別のページにジャンプしてもオブジェクトが残っているので、非常に便利です。このアプローチを使い始める前に、それが本当に良いアイデアなのか、それとも潜在的な落とし穴があるのか​​を知りたいと思います。

単一のエントリポイントがあれば、それを行う必要はないことはわかっていますが、まだそこにいないので、単一のエントリポイントがないので、オブジェクトを保持したいと思います。そのように私の状態を失います。(ステートレスサイトをプログラムする必要があることも読みましたが、その概念はまだ理解していません。)

つまりセッションにオブジェクトを保存しても大丈夫ですか、問題はありますか?


編集:

一時的な要約:データベースに再度クエリを実行する必要がある場合でも、オブジェクトを再作成する方がおそらく良いことを理解しています。

さらなる答えは、おそらくその側面についてもう少し詳しく説明することができます!

4

8 に答える 8

138

このトピックが古いことは承知していますが、この問題は何度も発生しており、満足のいく対処がされていません。

オブジェクトを $_SESSION に保存するか、非表示のフォーム フィールドに格納されたデータに基づいて布全体を再構築するか、毎回 DB から再クエリするかにかかわらず、状態を使用しています。HTTP はステートレスです (多かれ少なかれ; ただし、GET と PUT を参照してください) が、Web アプリで行うほとんどすべてのことは、どこかで状態を維持する必要があります。国家を隅から隅まで押し込むかのように行動することは、ある種の理論上の勝利につながるというのは、まったく間違っています。状態は状態です。ステートを使用すると、ステートレスであることによって得られるさまざまな技術的利点が失われます。これは、睡眠を失うべきだと事前にわかっていない限り、睡眠を失うものではありません。

私は、ハンク・ゲイの「二重苦」の議論によって得られた祝福に特に困惑しています。OP は、分散型で負荷分散された e コマース システムを構築していますか? 私の推測ではノーです。さらに、彼の $User クラスなどをシリアライズしても、彼のサーバーが修復できないほど機能しなくなることはないと思います。私のアドバイス: アプリケーションに適した手法を使用してください。$_SESSION 内のオブジェクトは、常識的な注意事項に従って問題ありません。あなたのアプリが突然、トラフィックの点で Amazon に匹敵するものになった場合は、再適応する必要があります。それが人生だ。

于 2012-02-05T15:39:38.090 に答える
114

session_start()呼び出しが行われるまでに、クラス宣言/定義がPHPによって既に検出されているか、すでにインストールされているオートローダーによって検出されている限り、問題ありません。そうしないと、セッションストアからオブジェクトを逆シリアル化できません。

于 2008-09-25T08:49:56.573 に答える
35

HTTPは、理由からステートレスプロトコルです。セッションは状態をHTTPに溶接します。経験則として、セッション状態の使用は避けてください。

更新:HTTPレベルでのセッションの概念はありません。サーバーは、クライアントに一意のIDを与え、要求ごとにそれを再送信するようにクライアントに指示することで、これを提供します。次に、サーバーはそのIDをSessionオブジェクトの大きなハッシュテーブルへのキーとして使用します。サーバーはリクエストを受け取るたびに、クライアントがリクエストで送信したIDに基づいて、セッションオブジェクトのハッシュテーブルからセッション情報を検索します。この余分な作業はすべて、スケーラビリティに対する二重の苦痛です(HTTPがステートレスである大きな理由)。

  • Whammy One:単一のサーバーで実行できる作業が減ります。
  • Whammy Two:リクエストを古いサーバーにルーティングするだけでは不十分なため、スケールアウトが難しくなります。すべてのサーバーが同じセッションを持っているわけではありません。特定のセッションIDを持つすべてのリクエストを同じサーバーに固定できます。これは簡単なことではなく、単一障害点です(システム全体ではなく、ユーザーの大部分にとって)。または、クラスター内のすべてのサーバー間でセッションストレージを共有することもできますが、ネットワーク接続メモリ、スタンドアロンセッションサーバーなど、より複雑になります。

これらすべてを考慮すると、セッションに入力する情報が多いほど、パフォーマンスへの影響は大きくなります(Vinkoが指摘しているように)。また、Vinkoが指摘しているように、オブジェクトがシリアル化できない場合、セッションは誤動作します。したがって、経験則として、セッションに絶対に必要なもの以上のものを入れることは避けてください。

@Vinko通常、追跡しているデータを返送する応答に埋め込み、クライアントに再送信させることで、サーバーストアの状態を回避できます。たとえば、非表示の入力でデータを送信します。サーバー側で状態を追跡する必要がある場合は、おそらくバッキングデータストアにあるはずです。

(Vinko氏は次のように付け加えています。PHPはセッション情報を保存するためにデータベースを使用できます。クライアントに毎回データを再送信させることで、潜在的なスケーラビリティの問題を解決できる可能性がありますが、クライアントがすべてを制御しているため、注意が必要なセキュリティ問題の大きな可能性があります。あなたの状態)

于 2008-09-25T08:51:51.280 に答える
20
  • シリアル化できない(またはシリアル化できないメンバーを含む)オブジェクトは、期待どおりに$_SESSIONから出てきません。
  • 巨大なセッションはサーバーに負担をかけます(毎回状態のメガライズとデシリアライズはコストがかかります)

それ以外は問題ありません。

于 2008-09-25T08:52:23.213 に答える
11

私の経験では、一般的に、いくつかのプロパティを持つStdClassよりも複雑なものには価値がありません。シリアル化を解除するコストは、セッションに保存された識別子を指定してデータベースから再作成する以上のコストでした。かっこいいようですが、(いつものように)プロファイリングが鍵となります。

于 2008-09-25T09:03:43.593 に答える
8

どうしても必要な場合を除いて、stateは使用しないことをお勧めします。セッションを使用せずにオブジェクトを再構築できる場合は、それを実行してください。Webアプリケーションに状態があると、アプリケーションの構築がより複雑になります。リクエストごとに、ユーザーの状態を確認する必要があります。もちろん、セッションの使用を避けられない場合もあります(例:ユーザーはセッション中にログインを維持する必要があります。 Webアプリケーション)。最後に、大きなオブジェクトをシリアル化および非シリアル化するパフォーマンスに影響を与えるため、セッションオブジェクトをできるだけ小さくすることをお勧めします。

于 2008-09-25T09:01:04.957 に答える
4

リソースタイプ(db接続やファイルポインタなど)はページの読み込み間で保持されないことを覚えておく必要があり、目に見えない形でこれらを再作成する必要があります。

また、セッションのサイズも考慮してください。保存方法によっては、サイズの制限や遅延の問題が発生する可能性があります。

于 2008-09-25T08:55:27.857 に答える
1

また、ソフトウェア ライブラリをアップグレードするときにも取り上げます。ソフトウェアをアップグレードしたところ、古いバージョンには V1 ソフトウェアのクラス名とセッション中のオブジェクトがありました。新しいソフトウェアは、セッション内にあったオブジェクトを構築しようとするとクラッシュしていました。ソフトウェアはそれらの同じクラスを使用しなくなったため、それらを見つけることができませんでした。セッション オブジェクトを検出し、見つかった場合はセッションを削除し、ページをリロードするために、いくつかの修正コードを挿入する必要がありました。最初に報告されたときにこのバグを再現していたことに最初に気をつけた最大の苦痛(あまりにもよく知られている、「まあ、それは私にとってはうまくいく」:)最近古いシステムと新しいシステムに出入りする人々にのみ影響を与えたからです-しかし、良いすべてのユーザーが確実にセッションに古いセッション変数を持っていて、すべてのユーザーがクラッシュする可能性があるため、起動前にそれを見つけました。

とにかく、修正案で提案されているように、オブジェクトを再作成する方が良いと思います。したがって、id を保存してから、各リクエストでデータベースからオブジェクトを取得する方が安全です。

于 2016-02-10T23:44:51.180 に答える