-
Notifications
You must be signed in to change notification settings - Fork 79
/
Copy pathexamples.xml
277 lines (268 loc) · 12.7 KB
/
examples.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
<?xml version="1.0" encoding="utf-8"?>
<!-- $Revision$ -->
<!-- EN-Revision: 184f3f7bd45643cb80f828d0bb001991ec3a5fad Maintainer: takagi Status: ready -->
<!-- CREDITS: shimooka,hirokawa -->
<appendix xml:id="session.examples" xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink">
&reftitle.examples;
<section xml:id="session.examples.basic">
<title>基本的な使用法</title>
<para>
セッションは、シンプルな方法で個々のユーザーのデータを格納する仕組みで、
個々のユーザーに対して一意なセッション ID を用意します。
これを用いて、複数ページにまたがるリクエストの間で状態の情報を永続させることができます。
セッション ID をブラウザに送信するときには、通常はセッションクッキーを利用します。
また、その ID を使って既存のセッションデータを取得します。
その ID やセッションクッキーが存在しなければ PHP に対して新たなセッションを作るよう伝え、
新たなセッション ID を生成します。
</para>
<para>
セッションの処理の流れは単純です。セッションを開始すると、
PHP はまず、(通常はセッションクッキーから受け取る) ID を使って既存のセッションを取得しようとします。
ID を受け取らなかった場合は新しいセッションを作成します。
セッションを開始すると、PHP はスーパーグローバル <varname>$_SESSION</varname>
にすべてのセッションデータを格納します。PHP スクリプトの処理が終了するときには、
スーパーグローバル <varname>$_SESSION</varname> の中身を自動的に受け取ってシリアライズし、
ストレージに送信します。この一連の操作にはセッション保存ハンドラを使います。
</para>
<para>
デフォルトでは、PHP が使う保存ハンドラは <parameter>files</parameter> です。これは
<link linkend="ini.session.save-handler">session.save_handler</link> で設定します。
このハンドラは、サーバー上の
<link linkend="ini.session.save-path">session.save_path</link> で指定した場所にセッションデータを保存します。
</para>
<para>
セッションを手動で開始するには <function>session_start</function> 関数を使います。
<link linkend="ini.session.auto-start">session.auto_start</link> に
<parameter>1</parameter> を設定している場合は、
リクエストの開始時に自動的にセッションを開始します。
</para>
<para>
通常は、PHP がスクリプトの処理を終了するときに、セッションは自動的に終了します。
手動でセッションを終了させるには <function>session_write_close</function> 関数を使います。
</para>
<para>
<example>
<title>
<varname>$_SESSION</varname>で変数を登録
</title>
<programlisting role="php">
<![CDATA[
<?php
session_start();
if (!isset($_SESSION['count'])) {
$_SESSION['count'] = 0;
} else {
$_SESSION['count']++;
}
?>
]]>
</programlisting>
</example>
<example>
<title>
変数を <varname>$_SESSION</varname> から削除する
</title>
<programlisting role="php">
<![CDATA[
<?php
session_start();
unset($_SESSION['count']);
?>
]]>
</programlisting>
</example>
</para>
<para>
<caution>
<para>
<literal>unset($_SESSION)</literal>によって
全ての<varname>$_SESSION</varname>を初期化してはいけません。
<varname>$_SESSION</varname>スーパーグローバル変数を用いた
セッション変数の登録ができなくなってしまうからです。
</para>
</caution>
</para>
<warning>
<para>
セッション変数において参照を使用することはできません。
他の変数への参照を復元する方法がないからです。
</para>
</warning>
<note>
<para>
ファイルベースのセッション (PHP のデフォルト) は、
<function>session_start</function> でオープンしたり
<link linkend="ini.session.auto-start">session.auto_start</link> で暗黙のうちに開始したりしたセッションのセッションファイルをロックします。
いったんロックがかかったら、そのスクリプトが終了するなり
<function>session_write_close</function> を呼んでセッションを閉じるなりしない限り、
他のスクリプトからはそのセッションファイルにアクセスできません。
</para>
<para>
これは、たとえば AJAX を使いまくっていて同時に複数のリクエストが発生したりするウェブサイトで問題になります。
この問題への対処方法として一番お手軽なのは、セッションに対して必要な変更が終わったらすぐに
<function>session_write_close</function> を呼ぶことです。スクリプトの最初のほうで呼ぶほうが好ましいでしょう。
あるいは、ファイルではなく別のバックエンド (同時アクセスに対応しているもの) を使うという手もあります。
</para>
</note>
</section>
<section xml:id="session.idpassing">
<title>セッションIDの受渡し</title>
<para>
セッションIDの通知を行うためには次の二つの方法があります。
<itemizedlist>
<listitem>
<simpara>
Cookies
</simpara>
</listitem>
<listitem>
<simpara>
URLパラメータ
</simpara>
</listitem>
</itemizedlist>
</para>
<para>
sessionモジュールは、両方の方法をサポートします。
Cookieは最適ですが、(クライアントがCookieを受け入れない可能性が
あるため)信頼性がなく、これに依存することができません。2番目の方
法は、セッションIDを直接URLに埋め込みます。
</para>
<para>
PHPには、透過的にリンクを変換する機能を有しています。
この実行時オプション
<literal>session.use_trans_sid</literal>が有効な場合、
相対URIは自動的にセッションIDを含むように変換されます。
<note>
<para>
<link linkend="ini.arg-separator.output">arg_separator.output</link>
&php.ini; ディレクティブにより、引数セパレータをカスタマイズする
ことができます。XHTMLに完全準拠するためには、ここに
&amp; を指定してください。
</para>
</note>
</para>
<para>
もしくは、セッションが開始している場合に定義されている定数 <constant>
SID</constant> を使用することもできます。クライアントが適当な
セッションクッキーを送信しなかった場合、この定数は <literal>
session_name=session_id</literal> の形式となります。
他方、送信された場合には、この定数は空の文字列に展開されます。
このため、この定数を無条件に URL に埋め込むことができます。
</para>
<para>
次の例は、変数の登録法および <constant>SID</constant>
を用いて他のページに正しくリンクする方法のデモです。
<example>
<title>単一のユーザーに関するヒット数を数える</title>
<programlisting role="php">
<![CDATA[
<?php
session_start();
if (empty($_SESSION['count'])) {
$_SESSION['count'] = 1;
} else {
$_SESSION['count']++;
}
?>
<p>
こんにちは、あなたがこのページに来たのは <?php echo $_SESSION['count']; ?> 回目ですね。
</p>
<p>
続けるには、<a href="nextpage.php?<?php echo htmlspecialchars(SID); ?>">ここをクリック</A>
してください。
</p>
]]>
</programlisting>
</example>
</para>
<para>
XSSに関係する攻撃を防止するために<constant>SID</constant>を出力する際に、
<function>htmlspecialchars</function>を使用します。
</para>
<para>
PHPをコンパイルする際に
<link linkend="ini.session.use-trans-sid">
--enable-trans-sid</link> を使用した場合、
上の例のように <constant>SID</constant> を出力する必要はありません。
</para>
<note>
<para>
相対URLでないURLは外部サイトを指していると仮定され、<constant>SID</constant>
が追加されません。これは、<constant>SID</constant>
を外部のサーバーに開示することはセキュリティ上のリスクとなる可能性があるためです。
</para>
</note>
</section>
<section xml:id="session.customhandler">
<title>カスタムセッションハンドラ</title>
<para>
セッション情報をデータベースに保存する機能か他の保存法を実装するには、
一連のユーザーレベルの保存関数を作成し、
<function>session_set_save_handler</function>を使用する必要があります。
<classname>SessionHandlerInterface</classname>
を使ったり、<classname>SessionHandler</classname> を継承して
PHP の内部セッションハンドラを拡張したりしてセッションハンドラを作成できます。
</para>
<para>
<function>session_set_save_handler</function> で指定したコールバックメソッドが、
セッションのライフサイクル内で PHP からコールされます。
セッションの <parameter>open</parameter>、<parameter>read</parameter>、<parameter>write</parameter>、
<parameter>close</parameter>、そしてセッションの削除 (<parameter>destroy</parameter>)
や定期的なガベージコレクション (<parameter>gc</parameter>) などのときです。
</para>
<para>
したがって、PHP では常にセッション保存ハンドラが必要となります。デフォルトは、通常はファイルベースの保存ハンドラです。
自作の保存ハンドラは <function>session_set_save_handler</function> で設定できます。
内部的な保存ハンドラとして、デフォルト以外のものも PHP の拡張モジュールとして用意されています。
<parameter>sqlite</parameter> や <parameter>memcache</parameter> そして
<parameter>memcached</parameter> などで、これらは <link linkend="ini.session.save-handler">session.save_handler</link>
で設定できます。
</para>
<para>
セッションが開始するときに、PHP は内部的に <parameter>open</parameter> ハンドラをコールします。
それに続けて <parameter>read</parameter> コールバックを実行し、
このコールバックがエンコードされた文字列を返します。これは最初にセッションストレージに渡されたものと同じ形式になります。
<parameter>read</parameter> コールバックがエンコードした文字列を返したら、
PHP がそれをデコードしてデコード後の配列をスーパーグローバル
<varname>$_SESSION</varname> に格納します。
</para>
<para>
PHP のスクリプトが終了するとき (あるいは <function>session_write_close</function> がコールされたとき) には、
PHP が内部的にスーパーグローバル <varname>$_SESSION</varname> をエンコードします。
そして、それをセッション ID とともに <parameter>write</parameter> コールバックに渡します。
<parameter>write</parameter> コールバックが終了すると、PHP は内部的に
<parameter>close</parameter> コールバックハンドラを実行します。
</para>
<para>
セッションが明確に破棄されたときには、PHP は
<parameter>destroy</parameter> ハンドラをセッション ID つきでコールします。
</para>
<para>
PHP はときどき <parameter>gc</parameter> コールバックを実行し、
設定されているセッション有効期限にもとづいて期限切れのセッションレコードを無効化します。
この処理では、最後にアクセスされてからの時間が <parameter>$lifetime</parameter>
を超えているすべてのレコードを永続ストレージから削除しなければなりません。
</para>
</section>
</appendix>
<!-- Keep this comment at the end of the file
Local variables:
mode: sgml
sgml-omittag:t
sgml-shorttag:t
sgml-minimize-attributes:nil
sgml-always-quote-attributes:t
sgml-indent-step:1
sgml-indent-data:t
indent-tabs-mode:nil
sgml-parent-document:nil
sgml-default-dtd-file:"~/.phpdoc/manual.ced"
sgml-exposed-tags:nil
sgml-local-catalogs:nil
sgml-local-ecat-files:nil
End:
vim600: syn=xml fen fdm=syntax fdl=2 si
vim: et tw=78 syn=sgml
vi: ts=1 sw=1
-->