0

I read some of the answers here and get "mind-locked". I am new and don't work at this, just taught myself over the last 43 years. I converted a piece of code from the hit counter I wrote the other day, and it simply counts the number of times an IP runs my denied access page. The code checks to see if the IP is already in the database table (unique). If it is, it simply increments and updates. If it isn't there, it inserts it with a value of 1.

All was well, then I noticed no increment when testing. So I isolated it and found that it won't recognize the table column value to update it, and it throws an exception when it tries to insert it as a new value because it is unique.

I have looked and looked and cannot seem to understand why it works fine in my hitcounter, but fails miserably here?!?

$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();

====================
OUTPUT:

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 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));
}    

bu 如果你想返回命中 - 你需要选择它们

于 2013-02-12T17:11:20.477 回答
1

问题是你正在检查两个不同的东西。当您使用准备好的语句问号时,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 回答