0

ここでいくつかの回答を読んで、「マインドロック」されます。私は新人で、この分野では働いていません。過去 43 年間、独学で学んできたばかりです。先日書いたヒット カウンターからコードを変換したところ、IP が拒否されたアクセス ページを実行した回数を単純にカウントします。このコードは、IP が既にデータベース テーブルに存在するかどうか (一意) を確認します。そうであれば、単純にインクリメントして更新します。存在しない場合は、値 1 で挿入します。

すべてが順調だったので、テスト時に増加がないことに気付きました。だから私はそれを分離し、それを更新するテーブルの列の値を認識しないことを発見し、それが一意であるため、新しい値として挿入しようとすると例外をスローします。

私は何度も見ましたが、ヒットカウンターではうまく機能するのに、ここでは惨めに失敗する理由を理解できないようです?!?

$IP = $_SERVER['REMOTE_ADDR'];
$IP = preg_replace('#[^0-9\.]#','',$IP);
$db_table = 'deniedcounter';
echo 'Enter denied_record.php<br />';
//$IP = str_replace('.','x',$IP);

function setdeniedcounter($IP, $db_handle, $db_table){
    $hits = null;
    $ip = "'".$IP."'";
    try{
        echo "SELECT * FROM $db_table WHERE ip = $ip".'<br />';
        $stmt = $db_handle->query("SELECT * FROM $db_table WHERE ip = $ip");
        $row_count = $stmt->rowCount();
        echo $row_count.' = Rows selected.<br />';
    }
    catch(PDOException $e){
        db_exception_handler($e);
    }
    if($row_count == 1){
        $row = $stmt->fetch(PDO::FETCH_ASSOC);
        echo $row['ip'].' '.$row['hits'].'<br />';
        $hits = $row['hits']; $ip = $row['ip'];
        $hits++;
        try{
            $stmt = $db_handle->prepare("UPDATE $db_table SET hits=? WHERE ip=?");
            $stmt->execute(array($hits, $ip));
            $affected_rows = $stmt->rowCount();
            echo $affected_rows.'<br />';
        }
        catch(PDOException $e){
            db_exception_handler($e);
        }
        exit();
    }
    elseif($row_count == 0){
        $hits = 1;
        try{
            $stmt = $db_handle->prepare($sql = "INSERT INTO $db_table(ip, hits) VALUES(?, ?)");
            $stmt->execute(array($ip, $hits));
            $affected_rows = $stmt->rowCount();
            //echo $affected_rows.'<br />';
        }
        catch(PDOException $e){
            db_exception_handler($e);
        }
    }
    //echo 'Hits = '.$hits.'<br />';
    if(isset($hits)){return $hits;}
}    

$db_handle = db_OPEN($db_host, $db_name, $db_username, $db_pwd);
if(strlen($IP) > 6){$da_hits = setdeniedcounter($IP, $db_handle, $db_table);}
if(!isset($da_hits)){$da_hits = setdeniedcounter('ALERT', $db_handle, $db_table);}
$db_handle = db_CLOSE($db_handle);
echo 'Exit denied_record.php<br />';
exit();

====================
出力:

Enter denied_record.php

SELECT * FROM deniedcounter WHERE ip = '127.0.0.1'

0 = Rows selected.

SQLSTATE[23000]: Integrity constraint violation: 1062 Duplicate entry ''127.0.0.1'' 
for key 'ip'

Exit denied_record.php
4

3 に答える 3

2

Mysql には特別な演算子があります。
最初に SELECT する必要はありません - 追加のコードで INSERT するだけです:

INSERT INTO $db_table(ip, hits) VALUES(?, ?) ON DUPLICATE KEY UPDATE hits=hits+1

だから、あなたの機能は実際には

function setdeniedcounter($ip, $db_handle, $db_table) {
    $sql  = "INSERT INTO $db_table(ip, hits) VALUES(?, 1) 
             ON DUPLICATE KEY UPDATE hits=hits+1";
    $stmt = $db_handle->prepare();
    $stmt->execute(array($ip));
}    

ヒットを返したい場合は、それらを選択する必要があります

于 2013-02-12T17:11:20.477 に答える
1

問題は、2 つの異なるものをチェックしていることです。準備済みステートメントの疑問符を使用すると、MySQL は独自の一重引用符を挿入します。したがって、最初に確認するのは、127.0.0.1 が存在するかどうかですが、存在しません。次に、'127.0.0.1' ( valueに一重引用符を含む) を挿入しようとしますが、これは既に存在するため、失敗します。

于 2013-02-12T17:11:34.943 に答える
-3

データベースの IP フィールドは文字列です。おそらく最初の sql ステートメントでは、引用符を使用する必要がありますか?

$db_handle->query("SELECT * FROM $db_table WHERE ip = $ip");

と置換する:

$db_handle->query("SELECT * FROM $db_table WHERE ip = '".$ip."'");
于 2013-02-12T17:10:36.087 に答える