[PHP-users 11348] Re: セッションについて
WADA Masashi
php-users@php.gr.jp
Thu, 07 Nov 2002 18:53:06 +0900
和田です。
>hoge.phpが動作している間、cancel.phpは実行されません。
>hoge.phpの動作を中断させる方法を教えて頂けないでしょうか?
matsu さんのスクリプトを次のように修正したら、中断が実現できま
した。
--- main.php ---------------------------------------------------------
<?php
session_start();
$id = session_id();
$_SESSION["status"] = "";
print <<<_END_OF_VALUE_
<html>
<head>
<script language="JavaScript">
<!--
function Exec() {
window.open(
"cancel.php",
"cancel",
'location=no, toolbar=no, menubar=no, status=no, '
+ 'directories=no, scrollbars=no, resizable=no, '
+ 'width=400, height=300'
);
setTimeout("document.a.submit()", 1000);
}
//-->
</script>
</head>
<body>
<form name="a" action="hoge.php" method="post">
<input type="button" value="exec" onclick="Exec()">
</form>
SESSION ID: $id<br>
</body>
</html>
_END_OF_VALUE_;
?>
----------------------------------------------------------------------
--- hoge.php ---------------------------------------------------------
<?php
$msg = "";
$timeoffset = time() + 20;
while(time() < $timeoffset)
{
session_start();
$id = session_id();
if($_SESSION["status"] == "cancel") {
$msg .= "canceled.<br>";
break;
}
session_write_close();
sleep(1);
}
$msg .= "end.<br>";
print <<<_END_OF_VALUE_
<html>
<head></head>
<body>
$msg<br>
SESSION ID: $id<br>
</body>
</html>
_END_OF_VALUE_;
?>
----------------------------------------------------------------------
--- cancel.php -------------------------------------------------------
<?php
session_start();
$id = session_id();
$msg = "";
if ($_POST["cmd"] == "exec_cancel") {
$_SESSION["status"] = "cancel";
$msg .= "canceled.";
}
print <<<_END_OF_VALUE_
<html>
<head></head>
<body>
<form name="a" action="cancel.php" method="post">
<input type="submit" value="cancel">
<input type="hidden" name="cmd" value="exec_cancel">
</form>
$msg<br>
SESSION ID: $id<br>
</body>
</html>
_END_OF_VALUE_;
?>
----------------------------------------------------------------------
このスクリプトの動作内容は次のとおりです。
(1).ブラウザで main.php にアクセス
(2).exec ボタンを押す。
→ cancel 用のウィンドウが開く
→ 元のウィンドウは hoge.php にアクセスする
(しかし hoge.php は 20 秒後にレスポンスを返す)
(3).cancel 用のウィンドウで cancel ボタンを押す
→ セッション変数 status に"cancel"がセットされる
(4).hoge.php でセッション変数 status を監視しており、"cancel"
がセットされたら、20秒が経過していなくてもその時点でレス
ポンスを返す。
今回の問題では(4)にポイントがあります。まず、PHPマニュアルの
session_write_close() を参照してください。
>セッションデータは、同時書き込みを防ぐためにロックされるため、
>ある時点であるセッションの処理ができるスクリプトは、1つだけです。
とあります。matsu さんのスクリプト hoge.php の
>------- hoge.php---------
>$timeoffset = time() + 20;
>while(time() < $timeoffset)
>{
> if($_SESSION["hoge"] == "1")
> break;
>}
この 20 秒の while ループでは、セッションデータがロックされ続け
ているため、cancel.php では session_start() で、hoge.php 側のセッ
ションデータの解放を待ちつづけることになります。
なので、hoge.php のループ内で、$_SESSION["hoge"] を監視しても
意味がありません。そこで次のように hoge.php を変更してみたわけで
す。
>$timeoffset = time() + 20;
>while(time() < $timeoffset)
>{
> session_start();
> $id = session_id();
>
> if($_SESSION["status"] == "cancel") {
> $msg .= "canceled.<br>";
> break;
> }
> session_write_close();
> sleep(1);
>}
>$msg .= "end.<br>";
ループの内部で、セッションを開始(session_start)し、セッション変
数 status の値が変化していないか確認した直後に、セッションを終了
(session_write_close)させています。これで、cancel.php 側でセッショ
ンを開始できる隙間を空けてあげるわけです。
(なお、システムに高負荷を与えないよう、1秒おきにチェックしてい
ます。)
・・・しかし、このようなセッション関数の利用方法を、私は今まで
に経験したことがありません。何かとんでもない問題が発生するかもし
れません。
----
和田雅志 (WADA Masashi)
wada@hh.iij4u.or.jp