PHP だけの言語を用いて、JavaScript Cookie session データベース使用無しのリロード対策作りました。
GET でアドレス後から付け加える方法も無しで、POST情報だけで実現しています。
やり方は、自分のページのAは描画をPHPで行う最に、自分のページA内に
任意のPOSTデータを含む情報を持つページAの形をした別物A’を読む、
そのA'はPOSTデータだけが違うという物。
つまり自分自身の分身A’を読み込んでPOSTデータ処理させる。
以下で説明するスクリプトの場合、初回と同様になる様に
空のデータを0扱いする様にしてあり、処理される。
私のブログにしては妙に短いのはお酒を・・・いるからですw(朝じゃん・・・・)
さてもう眠いですが、うれしさも何も無く酔い・・・いや、軽く頭が軽い状態で、
プログラムを組んでいた訳なんですが、そのソースを惜しげもなく(無様な汚いコードですw)
ここにメモ書きとして掲載しようじゃないか>w<;(早く寝たいですw)
さて、もとい。
ブラウザの違いとか検証は、いい加減にやってみました。(何度も言いますが眠いですw)
Internet Explorer 8 と、 Mozilla Firefox 3.6.17 そして、Safari 5.0.5(7533.21.1 ) ですが、
なぜか私の場合以下のファイル名がフルパスで
http://localhost/flipflop_reload_protect.php
なのですが、Safari だけは最後に / を追加した
http://localhost/flipflop_reload_protect.php/
とアドレス入力に入力しなければ初回の画面が見られませんでした。
Safari の意味不明な仕様に驚き、良いブラウザハックの拾い物をした!と思いつつ?
時間も時間なので次に進みたいと思いますw
では本ソースです。
<?php
header('Content-type: text/html; charset=UTF-8');
echo '前のPOSTだよ!';
var_dump($_POST);
if(!$_POST['flipflopProtect'])
{
echo '0の時だけ<br/><br/>';
//POSTデータ
$originalPOST = array(
'flipflopProtect' => !(boolean)$_POST['flipflopProtect'],
'count_submit' => 1 + (integer)$_POST['count_submit']
);
$mergePOST = array_merge($_POST,$originalPOST);
$contentData = http_build_query($mergePOST, "", "&");
//header
$header = array(
"Content-Type: application/x-www-form-urlencoded",
"Content-Length: ".strlen($contentData)
);
$context = array(
"http" => array(
"method" => "POST",
"header" => implode("\r\n", $header),
"content" => $contentData
)
);
$url = "http://localhost/flipflop_reload_protect.php";
echo file_get_contents($url, false, stream_context_create($context));
die();
}
?>
/* 本文(ホームページなど) */
うんたらうんたら・・・
<?php echo "<br/>\$_POST['flipflopProtect']がずっとブラウザ内では1なんですよ! 実際の値:" . $_POST['flipflopProtect'] ?>
<form id="reloadBlock" method="POST" action="<?php echo $_SERVER['REQUEST_URI'] ?>">
<input type="hidden" name="flipflopProtect" value="0" />
<input type="hidden" name="count_submit" value="<?php echo $_POST['count_submit']?>" />
<input id="submitBottun" type="submit" value="<?php echo $_POST['flipflopProtect']==1?'プロテクト中':'何処かにバグ' ?>" />
</form>
こんな感じでした。
簡単に説明すると
POSTデータの$_POST['flipflopProtect'] は、開始直後はstringでは''で、
これは数値式のinteger で表せば0です。
その0か''の時だけ、自分自身を参照しに行き、
その処理の時に$_POST['flipflopProtect'] を1にしてプロテクトをかけ、
リロード出来ない状態にして、リロードしても処理しない部分を作り上げています、
つまり自分自身にPOSTする処理を無くしています。
そんな感じで見栄えは一緒、でもPOSTデータの内容が違うと言うとてもとても危なげで
奇想天外な事をしています。
これは本当に苦肉の策みたいな物なので、
Webページとしての描画内容はPHPのそのリロードプロテクトの後に
書いている状態なので、その辺を一まとめにするかとか、
色々他のPHPスクリプトを付け加えて実践的にすると
どんな感じになるかとかまでは書いていません
(お酒飲んでいるから早くブログを書き終えたいですw朝ですしw)。
そんな感じです<_ _>
一応ですが書くとすると自身が表示させたい下部の
/* 本文(ホームページなど) */
と書いている部分以降に
if(!$_POST['flipflopProtect']){ ~~~~~ }
この ~~~~~ にリロード時に処理させたくない内容を入れればいいんです。
別に1ページのソース内に細切れに<?php そのソース ?>でいいと思うんです。
そんな感じで今回のメモは終わりにしたいと思います。
お酒入っているので、見直しは後ほどにします。
お休みっ! ^v^ノシ
追伸:(結構ウェイト大きいです)
なんかやはり、自身を参照している部分が不可思議な表示です。
推測ではキャッシュしている部分とPHP内部で計算してしまう部分と両方を用いて
描画しているのではないかと思います。
以下の修正変更したソースのカウントが動いてしまうのがその良い例です。
A=自身 A’=自身を呼び出した物とします。
また実はAとA'の両方にPOSTメッセージは存在し、別々に処理されています。
この当りもややこしいです。
そしてA'内部からAのグローバル変数やAのPOSTデータは操作できません。
書籍などには無い、不思議なブラウザとサーバ処理(ApacheやPHPの挙動)が見え隠れします、
環境に依存する可能性もあるので気をつけてください。
とりあえず初回もカウントしない様にして、内部の時間も数値化してみました。
A'の描画が不思議であるのがわかると思います。
/* 本文(ホームページなど) */
うんたらうんたら・・・
<?php echo "<br/>\$_POST['flipflopProtect']がずっとブラウザA内では0か''なんですよ! 実際の値:[" . $_POST['flipflopProtect'] . "]" ?>
<form id="reloadBlock" method="POST" action="<?php echo $_SERVER['REQUEST_URI'] ?>">
<input type="hidden" name="flipflopProtect" value="1" />
<input type="hidden" name="count_submit" value="<?php echo $_POST['count_submit']?>" />
<input id="submitBottun" type="submit" value="<?php echo $_POST['flipflopProtect']==1?'何処かにバグ':'プロテクト中' ?>" />
</form>
<?php echo var_dump($_POST) ?>
'<br/>リロードブロックと初回だけのはずなのに!<br/><br/>' って所が、カウントした場合でも表示されています。
このIF文はどちらかしか動かないからIFなのですが・・・
IFでそうであった場合と、そうでなかった場合、両方の結論が出てしまう様に見える!
キャッシュやインスタンスなどの絡みと読み込みの絡み、AとA'の関係から、
結果的にブラウザの持つAの変数操作はされている様な挙動を
かろうじて実現出来ている様ですが、実際の絡みが不明な為、
よーく考えて使うべきです。
私はフォームメールに実装しようと思います。
A'内で処理する部分にブラウザへの描画関数は用いない方が無難だと思います。
それはキャッシュやインスタンス内の何かをAで妙な反映をさせない対策になると思います。
Aはブラウザで表示できる物全ての処理をし、
A'は間違っても表示処理を入れない方が良いと言うことです。
多分・・・・それが無難で一番良い方法になると思います^^;
以上長ーーーーーいメモでした<_ _>
さてさて、毎回Web上にある設定の変更できないレンタルのサーバの環境とローカル環境の違いを把握して・・・どうのこうの・・・
みたいなややこしいことをしてきた結果、当たり前であろう事により一段と近づく結論が浮かんだ。
それは「設定の修正が効かない側のサーバ(レンタルサーバ)の環境に極力ローカルの開発環境も整える」こと。
という結論が出た、とても当たり前と言えば当たり前だ・・・。
文字化け以外にも、文字カウントを失敗するないていうことが、
デフォルトの 内部文字エンコーディング ->mbstring.internal_encoding (php.ini内)
や
関数で指定した内部文字エンコーディング ->mb_internal_encoding 関数
によって起こる事が判明した。
まず、この結論にたどり着くまでに気がついた事柄を述べる。
<まずテストする為のソースコード>
<?php
$string = '内部文字エンコーディング環境のTESTです!'.mt_rand(0,9).mt_rand(0,9).mt_rand(0,9);
// 文字の長さの検出の色々な仕方
var_dump(strlen($string)); //内部文字エンコーディングが違う環境に依存しない(バイト数)
var_dump(mb_strlen($string)); //内部文字エンコーディングが違う環境に確実に左右される
var_dump(mb_strlen($string ,'UTF-8')); //内部文字エンコーディングが違う環境に依存しにくい
?>
これを参考に以下、1. 2. 3. を見てもらえば判ると思う。
1.文字数をカウントする計算式に狂いが生じる。
内部エンコーディング:ISO-8859-1
と
内部エンコーディング:UTF-8
では部分的に違う出力結果になる。
内部エンコーディング:UTF-8 の場合、上から答えが int 61、 int 25、 int 25 となる。
内部エンコーディング:ISO-8859-1の場合、上から答えが int 61、 int 61、 int 25 となる。
2.カウントしたい文字列が1文字が1バイト以上の文字である場合には、
文字数カウントに使えない関数がある。
つまりこの例のスクリプトの場合は、
var_dump(mb_strlen($string)); //内部文字エンコーディングが違う環境に依存しない
がバイト数でしか文字列がカウントできないです。
そしてまた、文字としてカウントできるとしても、正しい文字エンコーディングを指定していない場合、
存在しない文字を他の文字に読み違えたりして間違って文字を認識したりした結果、
文字数が変わってしまうのが、
var_dump(mb_strlen($string)); //内部文字エンコーディングが違う環境に確実に左右される
です。
また、内部エンコーディングを指定して文字数をカウントさせているので、一番文字数のカウント間違えが
少ないと思われる、
var_dump(mb_strlen($string ,'UTF-8')); //内部文字エンコーディングが違う環境に依存しにくい
ですが、
依存しにくいと書いているのは、保存形式によって保存された文字が
本当に指定したコードで文字を間違えて文字化けなどをせずに解釈できるのかどうかの
テストは今回行っていないからです。
3.サーバの環境によってデフォルトの設定があるので、
文字数カウントの関数の引数が任意であっても指定した方が環境が変わっても、
スクリプトが同様に動く可能性が高くなる。
// 文字の長さの検出の色々な仕方
var_dump(strlen($string)); //内部文字エンコーディングが違う環境に依存しない
var_dump(mb_strlen($string)); //内部文字エンコーディングが違う環境に確実に左右される
var_dump(mb_strlen($string ,'UTF-8')); //内部文字エンコーディングが違う環境に依存しにくい
?>
何時もの様に、自由に迷ってみました、
そしてその迷ったこの思いをやはり何時もの様に、綴っておこうと思います。
(右往左往して毎度毎度間違えから何かを確実に少しづつですが得ていると思いますw)
複数のURLを意識せずに同時に開きたいと思って、
PHP のマニュアルで色々探してみた。
プロセス制御環境でPHPのスクリプトを同時に走らせようかと思ったが、
UNIX では動くがWindows では動かないとか、プラットフォームに依存する
関数が多くみられたので困った。
具体的には、PCNTL — プロセス制御 を使おうと思ったがその
プラットフォームに依存するので、OSに合わせて自動で切り替わる様な
スクリプトを書くのはどうも安定した結果が出せない気がしていました。
他にもそのプロセス制御で、セマフォ — セマフォ、共有メモリおよび IPC
とか、下記※の様な条件付きでの共有メモリなども含め複数のURLを同時に
取得する方法を入手しようかと思いましたがなかなか見つかりませんでした。
※「Windows 2000 より前のバージョンの Windows では共有メモリをサポートしていません。
Windows では、PHP が Apache や IIS などの web サーバモジュールとして稼動している場合にのみ」
そしてまたこれもこのブログを書きながら間違えだったと気が付いたのですが、
cURL という物がありました。
このcURL とは、例えばログイン処理してからしか見られないサイトなどで
ログインのアドレスやパスワードを元にログイン処理をしてから
ログインしてから見られない情報を得るなど、しっかり手順を追って処理出来るように
した物の様です。
私が欲しい物では無かった様ですが、ネット上で調べるとセオリーの様な話があるので
一応メモ書きをしている訳です^^;
cURL はWindows 環境で有効にするには、php.ini の中にある
;extension=php_curl.dll を使えば良い様です。
これの「;」を取り除き有効にします。
一応私は確認の為にPHP のext フォルダの中身を見て
中にphp_curl.dll がある事を確認しました。
また導入前のWindows 環境でphpinfo()関数を用いたとしても
cURL と言う言葉すら出てこないので、一瞬これは対応していなのかな?
と思いましたが、しっかりphp_curl.dll をphp.ini のextension を有効にして
Apache(私の場合)を再起動すればすぐに項目が現れました。
(私のApache 用のVC6コンパイルのPHP5.33の環境にて)
やはりWindow 環境で開発している分、そういうプロセス関係で
PHP のスクリプトを呼び出すなどは現在のPHP ではプラットフォームに
依存する様な書き方が一番性能が良い様で、プラットフォームを選ばない方法で
これだ!と思える関数やライブラリは無い様でした。
とりあえずは、Window の環境でのなんらかの方法を見つけ、
その後でWindow環境とLinux 環境でも使えるスクリプトを作れるなら
作ってみようと思った、しかしプラットフォームごとにプロセスの仕方が違うと
レスポンスなどは全く変わってしまうだろうと思う、私が思うに最大のネットアクセス数か
何かがWindow で改良というか改造を加えなければ、10にも満たない記憶がある、
これはDoS攻撃かなにかの踏み台にされない為にそうなったハズだが、
これを外す方法はある、いずれにせよやはりサーバはLinux(UNIX)の方が
有利であることは良くわかった・・・・PHPでさえも!・・・・
私は欲張った構想と、小さなテストプログラムを幾度も頭の中や紙や
ソース(スクリプト)上で書いてみて色々するタイプだが、考える事の方が
時間を取られる事もあり、頭の整理や実感をする為にこのブログを書いた事は
私らしくも恥ずかしいが否定できないだろうと思った。
以上メモでした。
追伸:
以上だと思ったが!!!
まだ桎梏(しつこく この漢字生まれて初めて使う、脱線気味でごめんw)追求していると
どうもこのcURL で並列に実行できそうだ!!!!!!!!!!
並列処理にもっていくには、cURL マルチハンドルに、通常の cURL ハンドルを追加するらしい。
その関数は、curl_multi_add_handle() という関数みたいだ。
ぶっちゃけ目から鱗&目から涙だ;v;wwww うれしすぎるw
これで私のしたい事がいっぱい終わりそうだ。
何度も言うがうれしいw よくやったPHP これからも期待している><bw
またも本格的に開発を進める前に、
Windows 7 のPC を手に入れてしまったので、
そちらのPC へ開発環境を入れようとした時にPHP のバージョンが
上がっていたのでついでにバージョンアップしようと思った。
私の行うWindows 環境のPHP の以降は極めて簡単で、
httpd はApache を用い、そこそこのマルチスレッドのPCなので
PHP のダウンロードはVC6 x86 Thread Safe のダウンロードをして
php.ini の内容を比較し、エディターで書き換えた物を用意し、
元のディレクトリーにあるPHP を消して、新しい物と置き換え、
Apache サービスを再開してみるだけである。
今回設定としてバージョンアップとして項目が関係しているのは
session.entropy_file の様です。
この項目は、session.entropy_file で指定したリソースに関しての
設定の様で、バイト数を指定し、デフォルトは、0 (無効)だそうです。
特にPHP 5.3.3 でこのsession.entropy_file で変わった所は、
ランダムでファイルパスと言うかIDを作ることの様です、この表現は間違っているかも
しれませんので、具体的には公式のページを見てください。
元々このsession xxx の設定の意味がよくわからなかったのですが
よく調べてみると、phpやWebでのセッションの意味が私が良くわかっていなかったのが
良くわかりました。
この場合のPHPのセッションとは、個別のコンピュータごとに
違う結果を残す為の仕組みの様です。
その場合のセッションの情報を残す為の場所を指定するのが、
session.entropy_file であり、その情報の読み取るバイト数を
session.entropy_length で決める様です。
関連の関数としては、
session_start 関数
session_register 関数
などがある様です。
まだセッションの設定は色々ある様ですが、
私はまだプログラミング出来ない、していない段階なので、
詳しくはgoogle検索をした方が良いでしょう。(私がwですww)
さて、後は元のphp 5.3.2 のphp.ini の内容を
5.3.3 の新しく使うphp.ini の設定に変更点や修正を書き込むだけです。
本当に個人的なメモになります、全く他人には当てにならないメモなので悪しからず。