if文がifにならない?
- 連続投稿防止のために、IPアドレスと時間を記録し、条件に基づいて処理を行っています。
- しかし、条件分岐が正しく機能せず、予想外の結果が得られています。
- in_array関数が期待通りに機能しない理由や、if文の動作に問題がある可能性について調査が必要です。
- ベストアンサー
if文がifにならない?
よろしくお願いします。 連続投稿防止の為に、getenvで取得したIPアドレスと time()で取得した時間をcsvファイルに xxx.xxx.xxx.xxx<>1249494949 xxx.xxx.xxx.xxx<>1249494949 という風に記述をしてます。 具体的には、 <?php $ipdesu = "./ip.csv"; $ipgetdesu = getenv( "REMOTE_ADDR"); $times = time(); $hoge = 0; $roop_open = fopen( $ipdesu, "r"); while(! feof($roop_open)){ $roop_get = fgets( $roop_open); $roop_ex = explode( "<>", $roop_get); $hogehoge = $hoge++; //IPチェック if( in_array( $ipgetdesu, $roop_ex)){ echo "配列検索TRUE"; //時間チェック if ( "60" < $times - $roop_ex[1]){ $fp = file( $ipdesu); unset( $fp[$hogehoge]); $fp_open = fopen( $ipdesu, "w"); foreach ( $fp as $value){ fputs( $fp_open, $value); } fclose( $fp_open); }else{ echo "連投規制"; } }else{ $fal_open = fopen( $ipdesu, "a"); fputs( $fal_open, $ipgetdesu."<>".time()."\n"); fclose( $fal_open); echo "配列検索FALSE"; } } fclose( $roop_open); ?> と記述しています。 <まだ、始めたばかりなのでロック制限とかしてませんがそこはご勘弁を 上記を実行すると、if ここ else そこ の本来、真であれば「ここ」が 偽であれば「そこ」だけが実行されると思っていたのですが、 上記の実行結果は、「ここ」も「そこ」も実行されてしまい かつ、IPを記述したファイルの検索が2回め実行した時に 同じIP 127.0.0.1<>時間 127.0.0.1<>時間 とローカルで試してるのでIPが変更になるはずないのですが(DHCPは念の為しようしていません in_arrayでヒットしないのは何故でしょうか? また、ifが正しく動作しないのは多重ifとでも言えばいいのでしょうか? が悪いからでしょうか。 つたないソースで申し訳ないですが、どうかよろしくお願いします。
- nnoelst
- お礼率80% (4/5)
- PHP
- 回答数5
- ありがとう数5
- みんなの回答 (5)
- 専門家の回答
質問者が選んだベストアンサー
全角空白でインデントを入れてみました。 $roop_open = fopen( $ipdesu, "r"); while(! feof($roop_open)){ $roop_get = fgets( $roop_open); $roop_ex = explode( "<>", $roop_get); $hogehoge = $hoge++; if( in_array( $ipgetdesu, $roop_ex)){ echo "配列検索TRUE"; //時間チェック if ( "60" < $times - $roop_ex[1]){ $fp = file( $ipdesu); unset( $fp[$hogehoge]); $fp_open = fopen( $ipdesu, "w"); foreach ( $fp as $value){ fputs( $fp_open, $value); } fclose( $fp_open); }else{ echo "連投規制"; } }else{ $fal_open = fopen( $ipdesu, "a"); fputs( $fal_open, $ipgetdesu."<>".time()."\n"); fclose( $fal_open); echo "配列検索FALSE"; } } if , else の構文自体は問題ないと思いますが 過去投稿を記録している ip.csvを fgetsで1行毎に読み込んで 合致しているかの処理にしているので、読み込んだ ip.csvの 1行目では、if文が真のときの処理 2行目では、if文が偽のときの処理 といった感じで、ip.csvの行数だけ、何度も処理を実行している という感じではないでしょうか。 しかも、読み込み中のファイルに対して、 同じファイル名を書き込みオープンして、上書きしているのも、 おかしなことになりそうです。 読み込みするwhile内では、連続投稿があったかどうかのフラグだけとり、 whileが抜けてから、そのフラグによって、 ファイルの上書き処理をする形がよいかと思います。 (ファイルのロック処理は別途) それと、クライアントのIPアドレスは getenv( "REMOTE_ADDR"); でなく、 $_SERVER['REMOTE_ADDR'] ですね。
その他の回答 (4)
- A88No8
- ベストアンサー率52% (834/1602)
こんにちは #1です。 >while(! feof($roop_open)){ 本当にごめんなさい。 見落としてました。でも、有識者の方の適切なアドバイスがあってよかったです。
- UmJammer
- ベストアンサー率58% (115/196)
ip.csvのファイルの末尾に改行コードが挿入されているため、whileでまわしたとき最後に空行が処理され、そのとき$roop_exは空文字列となり、そのため後続のin_arrayで想定外の動きをしてしまっている状態と思われます。 一番最初(ip.csvが空のとき)は正常に動作すると思いますが、それはたまたまということになります。 個人的には連投の判定部分とip.csvへの書き込み部分の処理は分けた方が良いような気がします。
お礼
お返事有難うございます。 空文字削除の為に、trim系列?の関数を試していますが 中々、最後の行だけ削除が出来ても どうして、次のループでまた旨く逝かないとかてこずってます。 書き込み部分の処理分けは、まだ未熟な為 そこまで頭が回りませんが(ユーザー関数とかなんでしょうか。 また、次回作成時頑張ってみます。 今は、目の前の壁に全力投球します! 出口が見えそうで見えないのは、 なんともいやはや歯がゆいですね。
補足
同じ文章になってしまいますが、 ここに投稿したおかげでなんとなく脱け出せそうです。 回答して頂いて有難う御座いました。
- yambejp
- ベストアンサー率51% (3827/7415)
in_array()の挙動に疑問があるのであれば その直前行に、 print_r($ipgetdesu); print_r($roop_ex); などして、整合性があっているかデバッグしてみてはどうでしょうか?
お礼
お返事有難うございます。 直前に print_r($ipgetdesu)."<br>\n"; print_r($roop_ex); if( in_array( $ipgetdesu, $roop_ex)){ と記述してみたところ 127.0.0.1 Array ( [0] => 127.0.0.1 [1] => 1249450592 ) 配列検索TRUE連投規制 と表示されているので整合性は問題ないと思うのですが。 何か他のデバッグ方法はありますか? 一応、if直後とかに何がどう表示されるか等チェックはしているのですが いかんせん内部でどのような処理が行われているかが謎ですので、 困り果ててます。
補足
同じ文章になってしまいますが、 ここに投稿したおかげでなんとなく脱け出せそうです。 回答して頂いて有難う御座いました。
- A88No8
- ベストアンサー率52% (834/1602)
こんにちは PHPという言語システムについては、全くの門外漢ですので参考まで。 下記のように//IPチェックから以降をインデントを付けてみました。 門外漢が見てですがif文の書き方(ブロックの書き方)が"連投規制"後に、余ってしまっているように見えます。 もう一度ブロックを見直してみて下さい。 //IPチェック if( in_array( $ipgetdesu, $roop_ex)){ echo "配列検索TRUE"; //時間チェック if ( "60" < $times - $roop_ex[1]){ $fp = file( $ipdesu); unset( $fp[$hogehoge]); $fp_open = fopen( $ipdesu, "w"); foreach ( $fp as $value){ fputs( $fp_open, $value); } fclose( $fp_open); }else{ echo "連投規制"; } }else{ $fal_open = fopen( $ipdesu, "a"); fputs( $fal_open, $ipgetdesu."<>".time()."\n"); fclose( $fal_open); echo "配列検索FALSE"; } } fclose( $roop_open); ?>
お礼
お返事有難うございます。 余っているというのは、処理の空白部分があるとい解釈でよろしいでしょうか? いまいちwhileの挙動について理解が足りていませんが、 もしかして、 if 真 if 真 もしくは 偽 の後はwhileを抜けない? という事で処理が手持ちぶたさなのでしょうか。 念の為、連投規制の後と、その一つ手間の fclose($fp_open) に break; を設けてみた所 綺麗にIPを除去してから再び追記してるかと思いきや、 一気に、3個同じ行を作成したりと謎な動作をしてます。 更新ボタンを連打しなくてもそうなるようです。
補足
ここに投稿したおかげでなんとなく脱け出せそうです。 回答して頂いて有難う御座いました。
関連するQ&A
- 何がおかしいのでしょうか?
$filename1 = 'ymd.dat'; $fp1 = fopen($filename1, "r+"); $day2 = fgets($fp1,9); $day = date('Ymd'); //今日のアクセス数カウント。日付が変われば0になる。 $filename2 = 'ymd2.dat'; $fp2 = fopen($filename2, "r+"); $count2 = fgets($fp2,32); if($day==$day2){ $count2++; fseek($fp1, 0); fputs($fp1, $day); fclose($fp1); }else{ $count2 = 0; fseek($fp1, 0); fputs($fp1, $day); fclose($fp1); } fseek($fp2, 0); fputs($fp2, $count2); fclose($fp2);
- 締切済み
- PHP
- LOCK_EXはifの条件になり得るのか?
$fp = fopen("/tmp/lock.txt", "r+"); if (flock($fp, LOCK_EX)) { // 排他ロックを確保します ftruncate($fp, 0); // ファイルを切り詰めます fwrite($fp, "ここで何かを書きます\n"); fflush($fp); // 出力をフラッシュしてからロックを解放します flock($fp, LOCK_UN); // ロックを解放します } else { echo "ファイルを取得できません!"; } fclose($fp); PHPのマニュアルサイトに書いてあった例文なのですが、たぶんロックできなかった場合は「ファイルを取得できません!」に出るようにするというものだと思います。 ただ、LOCK_EXはロックできない場合は、ロックできるようになるまで待ちますよね? だとすると、このif文ってelseは機能しないと思うんですが、どうなんでしょうか? もしかしてLOCK_EXは時間制限があって、待ち状態が何分も続くとタイムアウトとしてFalseを返す? そのときにelseが動くということでしょうか? この例文の下にLOCK_NBを使ったものもあるので、LOCK_EXの動作を勘違いしてるとは思えません。 この例文はどのタイミングの時にFalseを返して、elseが動くのでしょうか? http://php.net/manual/ja/function.flock.php
- 締切済み
- PHP
- if文について
cshで書いています。 if文がとおりません。。。 0: Event not found. このようなメッセージが出力されます。 if ($flg == "xxx") then echo "aaa" else if($flg == "yyy") then echo "bbb" exit else echo "ccc" exit endif 内容は上記のような感じです。 どなたか教えて下さい。
- ベストアンサー
- その他(プログラミング・開発)
- 条件文について
PHPのサンプルを勉強していると 簡単な構文でも「if」などの条件文が 必要以上に使われ故意に複雑にしているように見えます。 -------------------------------------- if(!empty($name) || !empty($naiyou)){ $keijiban = "keijiban.txt"; $fp = fopen($keijiban, "a"); if($fp){ if (flock($fp, LOCK_EX)){ if (fwrite($fp, $data) === FALSE){ print "ファイル書き込みに失敗しました"; } flock($fp, LOCK_UN); }else{ print "ファイルロックに失敗しました"; } } fclose($fp); } ----------------------------------------- 上記は正しいサンプル構文になるようで、 流れは大体理解できるのですが そんなところまで条件分岐をしなくてはいけないのかな? と思ってしまいます。 初学者の私が上のサンプルと同じ内容の構文を書くとしたら 以下のように条件分岐をできるだけ 少なくして考えてしまいます。 ----------------------------------------- if(!empty($name) || !empty($naiyou)){ $fp = fopen("keijiban.txt", "a"); flock($fp, LOCK_EX); fwrite($fp, $data); flock($fp, LOCK_UN); fclose($fp); }else{ print "エラー"; } ----------------------------------------- 条件分岐をできるだけ多く使うことは 必要なのでしょうか? 条件分岐で詳細に分けるのは どのような利点が具体的にあるのでしょうか? よろしくお願いいたします。
- ベストアンサー
- PHP
- Bシェルのif文
if文の否定について教えてください。 if $aa='xxx' then else echo yyy fi 間違っているかもしれませんが上に書いたことをやろうとしています。 他の言語の if(!($aa='xxx'))echo yyy; をBシェルのif文で書くにはどうしたらいいですか? $aa='xxx'を$aa!='xxx'にするのではなくて、その外側のifの書式を教えてください。 最初に書いたコードでは、if(!条件)を知らないので if(条件) else 処理 endif のように書きました。
- 締切済み
- その他(プログラミング・開発)
- phpである処理をすると数を1足して、ある処理をするとその数字から1引
phpである処理をすると数を1足して、ある処理をするとその数字から1引くような事をしたいのですが、上手くいきません。(まれに数字にずれが生じてしまいます。) 1足していくもの $fp = fopen("./data/registry/buy.dat","r+"); $registry_count = fgets($fp,1024); if($registry_count == ""){ $registry_count = 0; } $registry_count++; flock($fp,LOCK_EX); fseek($fp,0); fputs($fp,$registry_count); flock($fp,LOCK_UN); fclose($fp); 1引いていくもの $fp = fopen("./data/registry/buy.dat","r+"); $registry_count = fgets($fp,1024); if($registry_count != "0"){ $registry_count--; } flock($fp,LOCK_EX); fseek($fp,0); ftruncate($fp,0); fputs($fp,$registry_count); flock($fp,LOCK_UN); fclose($fp); どなたかご教授ください。 よろしくお願いいたします。
- ベストアンサー
- PHP
- PHPから書き換え
尻取りゲーム用に書いたPHPスクリプトの一部ですが CGIに書き換える方法がよくわかりません。 教えていただけませんでしょうか。 ============================================ if(isset($_POST['shiritori'])){ $rest = mb_substr($shiritori, -1, 1, "SJIS"); $hajime = mb_substr($shiritori, 0, 1, "SJIS"); if(($name != "") && ($shiritori != "")){ if($hajime == $key){ setcookie("name", $name, $expire); $key = file($keyfile); $fp = fopen($keyfile, "w"); fputs($fp,$rest); fclose ($fp); $word = "".$shiritori."<hr>"; $lines = file($logfile); $fp = fopen($logfile, "w"); fputs($fp,$word); for($i = 0; $i < $logmax-1; $i++) fputs($fp, $lines[$i]); fclose ($fp); } } else{ print"記入漏れはありませんか<br>"; print"次は<b>" .$key. "</b>から始まる語です。<br>"; } ============================================ どうぞよろしくお願いします。
- 締切済み
- CGI
- PHPアクセスカウンター
<?php $filename = 'count.dat'; $fp = fopen($filename, "r+"); $count = fgets($fp,32); $count++; fseek($fp, 0); fputs($fp, $count); fclose($fp); echo ($count); ?> これを日付が変わったら0にリセットしてくれるシステムにしたいんですが、どうしたらいいですか??
- ベストアンサー
- PHP
- 同じような処理を一つにまとめたい
count.txt <?php $dis123=0; $dis001=0; $hoge01=0; ?> ___________ counter.php <?php $vote = $_GET[vote]; $fp = fopen("count.txt", "r+"); include("count.txt"); @flock($fp,LOCK_EX); //今現在(カウント前)の値を書き込む fputs($fp,"<?php \$dis123=$dis123; ?>\n"); fputs($fp,"<?php \$dis001=$dis001; ?>\n"); fputs($fp,"<?php \$hoge01=$hoge01; ?>\n"); //GETで得た情報からカウントした物に+1して書き込む if ($vote===dis123){ ++$dis123; fputs($fp,"<?php $$vote=$dis123; ?>\n"); } if ($vote===dis001){ ++$dis001; fputs($fp,"<?php $$vote=$dis001; ?>\n"); } if ($vote===hoge01){ ++$hoge01; fputs($fp,"<?php $$vote=$hoge01; ?>\n"); } flock($fp,LOCK_UN); fclose($fp); echo "dis123は".$dis123."点<br>"; echo "dis001は".$dis001."点<br>"; echo "hoge01は".$hoge01."点<br>"; ?> _________________________________ 処理: counter.php?vote=dis123ときたらif処理して$dis123に+1する ________________________ 今は三つだからまだ大丈夫ですが、これが増えてくると手間が多いです そこで上記の今現在の値の書き込みとIF処理の部分を代入など、なんらかの形で簡略化できませんでしょうか?大改編になっても結構です。 よろしくお願いします。 備考:PHP暦三日目です、ここまでなんだかんだがんばったと思う。
- ベストアンサー
- PHP
お礼
お返事有難うございます。 >if , else の構文自体は問題ないと思いますが 中略 >という感じではないでしょうか。 凄く納得出来ました。 なるほど、そういう処理の仕方だったんですね。 >しかも、読み込み中のファイルに対して、 >同じファイル名を書き込みオープンして、上書きしているのも、 >おかしなことになりそうです。 いったん別名で保存してから内容の反映をしようと思ったのですが、 余計にややこしくなると思った処理が 余計にややこしくしてたんですね。 勉強になります。 まだ、ループを抜けての処理というのを 簡単な処理しかした事がないのでチャレンジしてみたいと思います。 $_SERVER['REMOTE_ADDR'] に変更して処理をしてみようと思います。
補足
同じ文章になってしまいますが、 ここに投稿したおかげでなんとなく脱け出せそうです。 回答して頂いて有難う御座いました。 一度、じっくり考えたいと思いますので 締め切らせて頂きたいと思います。 皆さん有難うございました。