-3

私は自分のページの訪問用のカウンターを作成しようとしました。これは、1日に1回だけ各IPをカウントします。見つかったコードを転記して、それがどのように機能するかを理解し、後で他のいくつかの機能を実装しました。残念ながら、私の新しいコードは機能しません。

私がそれから作ったコード:

<?php
$timeReset = 86400; //24h
$ipPath = "ipsafe.txt";
$countPath = "counts.txt";
$timePath = "time.txt";

$ip = $REMOTE_ADDR;
$time = time();
$resetTime = $time+$timeReset;

$timeFile = fopen($timePath, "r+");
$timeData = fread($timeFile, filesize($timePath));
//if resetTime is passed -> Reset
if($time >= $timeData) {
    //clear ipSafe
    $ipFile1 = fopen($ipPath, "w+"); 
    fclose($ipFile);
    //set new resetTime
    rewind($timeData);
    fwrite ($timeData, $resetTime);
}
fclose($timeFile);

//creat IP-List
$ipData = file($ipPath);
while (list ($line_num, $line) = each ($ipData)) {
    $digits = explode(",",$line);
}
//if IP was not saved in last timeframe
if(!in_array($ip, $digits))
{
    //write new IP
    $ipFile2=fopen($ipPath, "a+");
    @flock($ipFile1,2);
    fwrite($ipFile2, "$ip".",");
    @flock($ipFile1,3);
    fclose($ipFile2);
    //increment counter
    $countFile = fopen($countPath,"r+");
    $countData = fread($countFile, filesize($countPath);
    rewind($countFile);
    $countData++;
    fwrite($countFile, $countData);
    fclose($countFile);
}
?>

次の質問で:

  • 私のコードの何が問題になっていますか?

  • flockはファイルへのアクセスを管理するために使用されますが、なぜ同じファイルに異なる名前を使用する必要があるのですか?

あなたの提案をありがとう。

編集:

問題の説明にあまり具体的でなくてすみません。デバッガーを統合した後、「REMOTE_ADDR」を「$ _ SERVER ['REMOTE_ADDR']」に変更したため、1つのエラーを修正しました。今、私は次の問題を抱えています:

Warning: fopen(time.txt): failed to open stream: No such file or directory in .../counter.php on line 15

しかし、ファイルはcounter.phpと同じディレクトリにあります-もちろん、freadとfilesizeも失敗しました

Warning: fopen(ipsafe.txt): failed to open stream: Permission denied in .../counter.php on line 20

ファイルはまだ存在していませんが、「fopen($ ipPath、 "w +");」と思いました。存在しない場合は作成します。

Fatal error: Call to undefined function fb() in .../counter.php on line 26

「fb($ timeFile);」ではありません 値をfirePHPに送信しますか?

4

1 に答える 1

0

完全なコードレビューを行わない場合(コードがほぼ完全に書き直されることになります)、リストされている問題を修正するために変更することをお勧めします。

次の行$REMOTE_ADDRでは、未定義のを使用しています。

$ip = $REMOTE_ADDR;

あなたはおそらく$_SERVER['REMOTE_ADDR'](あなたが編集で確認した)使用するつもりだったので、その行は次のようになります:

$ip = $_SERVER['REMOTE_ADDR'];

ファイルを開こうとするとエラーが発生したとのことtime.txtです:「そのようなファイルまたはディレクトリはありません」。また、ファイルが-と同じディレクトリに存在していると言いますが、counter.phpそれでもこのエラーが発生します。これは、2つのことのうちの1つを意味する可能性があります。まず、ファイルが存在せず、あなたは間違っています。2つ目は、counter.phpファイルが、それを実行しているスクリプトとは異なるディレクトリにあることです。これは、time.txtファイルが実行中のスクリプトのディレクトリにある必要があることを意味します。これには2つのことをお勧めします。

1つ目は、ファイルが実際に存在する場合は、絶対パスを使用します。

$timePath = '/path/to/your/files/time.txt';

次に、ファイルが(コードで)存在するかどうかを確認し、存在しない場合は作成します。fopen()with r/ r+flagsは、ファイルが存在しない場合はファイルを作成しないため、手動で行う必要があります。コードを次のように変更してみてください。

if (!file_exists($timePath)) touch($timePath);
$timeFile = fopen($timePath, 'r+');
if ($timeFile) {
    // the rest of your code
}

ファイルを開くときにエラーが発生したとのことですipsafe.txt:「アクセスが拒否されました」。これは楽しいものです。行番号はサンプルコードと一致しませんが、これらは問題の行であると思います。

//clear ipSafe
$ipFile1 = fopen($ipPath, "w+"); 
fclose($ipFile);

最初の問題は$ipFile1、コードで決して使用しないことです(誤ってロック/ロック解除する場合を除きます。その情報については、以下を参照してください)。2つ目は、を呼び出すことですfclose($ipFile);$ipFile!という名前のハンドルはありません。これらのコード行を削除できます!

rewindファイル内のファイルポインタにtime.txt新しい時刻を書き込もうとします$timeDataが、ファイル自体ではなく、ファイルから読み込んだ値を使用しています$timeFile。行を次のように更新します。

rewind($timeFile);
fwrite($timeFile, $resetTime);

もう一度ファイルを読み込んで、ipsafe.txtIPアドレスの完全なリストを確認します。現在のユーザーのIPがファイルに含まれていない場合は、ファイルを追加します。これは論理的な問題である可能性がありますが、ファイルの最後の行のIPアドレスのみをチェックしていますが、それでもアイテムのすべての行を繰り返し処理しています。コードのコメントによると://if IP was not saved in last timeframe、これはあなたがやろうとしていることだと思いますが、if念のために、ループの下に表示されるフルステートメントブロックをループの内側に移動することをお勧めします。

これが楽しいブロックです:

//write new IP
$ipFile2=fopen($ipPath, "a+");
@flock($ipFile1,2);
fwrite($ipFile2, "$ip".",");
@flock($ipFile1,3);
fclose($ipFile2);

ファイルを$ipFile22)で開き、完全に異なるファイル$ipFile11 )をロックし、 2に書き込み、1のロックを解除してから、 2を閉じます。あなたの意図は2をロック/ロック解除することだったと思いますが、これはここでは完全に理にかなっているので、これらの行でに変更$ipFile1することをお勧めし$ipFile2ます。

それは(潜在的に)それを行うべきです。結局のところ、コードは次のようなものに似ているはずです。

<?php
$timeReset = 86400; //24h
$ipPath = "ipsafe.txt";
$countPath = "counts.txt";
$timePath = "time.txt";

$ip = $_SERVER['REMOTE_ADDR'];
$time = time();
$resetTime = $time+$timeReset;

if (!file_exists($timePath)) touch($timePath);
$timeFile = fopen($timePath, "r+");
if ($timeFile) {
    $timeData = fread($timeFile, filesize($timePath));
    //if resetTime is passed -> Reset
    if($time >= $timeData) {
        //set new resetTime
        rewind($timeFile);
        fwrite ($timeFile, $resetTime);
    }
    fclose($timeFile);

    //creat IP-List
    $ipData = file($ipPath);
    while (list ($line_num, $line) = each ($ipData)) {
        $digits = explode(",",$line);
    }
    //if IP was not saved in last timeframe
    if(!in_array($ip, $digits)) {
        //write new IP
        $ipFile2=fopen($ipPath, "a+");
        @flock($ipFile2, LOCK_EX);
        fwrite($ipFile2, "$ip".",");
        @flock($ipFile2, LOCK_UN);
        fclose($ipFile2);
        //increment counter
        if (!file_exists($countPath)) touch($countPath);
        $countFile = fopen($countPath,"r+");
        if ($countFile) {
            $countData = fread($countFile, filesize($countPath);
            if (empty($countData)) $countData = 0; // initialize the counter to '0' if it hasn't been set
            rewind($countFile);
            $countData++;
            fwrite($countFile, $countData);
            fclose($countFile);
        }
    }
}
?>

さて、あなたの$resetTime変数に関するもう1つの論理的な問題もあります。理想的には、1日単位で増分することは、指定されたタイムスタンプに24時間を追加することです(24時間= 86400秒)。ただし、夏時間はこれを破ります。次の代わりに:

$resetTime = time() + 86400;

別のルートを試してみてください(これが心配な場合は、つまり):

$resetTime = strtotime('+1 day');
于 2012-10-01T14:58:46.537 に答える