2010-05-26 43 views
2

我有一个包含一个无符号整型字段来存储访问者的IP地址的数据库表中插入IP地址:PHP /库MySQLi:与mysqli_stmt_bind_param()

`user_ip` INT(10) UNSIGNED DEFAULT NULL, 

这里是PHP代码片断它试图存储IP地址:

$ipaddr = $_SERVER['REMOTE_ADDR']; 
if ($stmt = mysqli_prepare($dbconn, 'INSERT INTO visitors(user_email, user_ip) VALUES (?,?)')) 
{ 
    $remote_ip = "INET_ATON('$ipaddr')"; 
    mysqli_stmt_bind_param($stmt, 'ss', $email, $remote_ip); 
    if (mysqli_stmt_execute($stmt) === FALSE) return FALSE; 
    $rows_affected = mysqli_stmt_affected_rows($stmt); 
    mysqli_stmt_close($stmt); 
} 

INSERT操作成功,但user_ip字段包含空值。 我也尝试将mysqli_stmt_bind_param()(在上例中设置为字符串)中的参数类型更改为整数,即mysqli_bind_param(...'si',...) - 但无济于事。

我也使用的代码,而不是MySQL的INET_ATON()SQL函数以下位尝试:

function IP_ATON($ipaddr) 
{ 
    $trio = intval(substr($ipaddr,0,3)); 
    return ($trio>127) ? ((ip2long($ipaddr) & 0x7FFFFFFF) + 0x80000000) : ip2long($ipaddr); 
} 

它仍然没有工作 - “user_ip”字段仍设置为null。我试过把mysqli_bind_param()中的整数&字符串传给$ ip_addr变量 - 无济于事。

看来问题在于参数化插入。

下“旧式”代码工作没有任何问题:

mysqli_query(..., "INSERT INTO visitors(user_email, user_ip) VALUES ('$email',INET_ATON('$ipaddr'))"); 

什么我错在这里做什么?

在此先感谢!

回答

2

我想应该是这样的:

$ipaddr = $_SERVER['REMOTE_ADDR']; 
if ($stmt = mysqli_prepare($dbconn, 'INSERT INTO visitors(user_email, user_ip) VALUES (?, INET_ATON(?))')) 
{ 
    mysqli_stmt_bind_param($stmt, 'ss', $email, $ipaddr); 
    if (mysqli_stmt_execute($stmt) === FALSE) return FALSE; 
    $rows_affected = mysqli_stmt_affected_rows($stmt); 
    mysqli_stmt_close($stmt); 
} 

的说明第二的变化?并将哪些参数发送到mysqli_stmt_bind_param。

由于您传入mysqli_stmt_bind_param的参数应该是要插入的实际值,而不是任何函数。

+0

哇!这很快! 谢谢!它现在工作! – invarbrass 2010-05-26 21:37:37

+0

很高兴我可以帮助:)绑定这样的参数的一些要点是让它们安全地插入到数据库中,以确保没有值意外地被解析为例如MySQL函数并正确地转义字符。 – becquerel 2010-05-26 21:54:51

+0

多数民众赞成认为,这是完美的解决方案/。 – AMB 2014-09-08 17:04:58

1

绑定SQL查询参数只能用于值,而不能用于表达式或函数调用。所以,当你这样做:

$remote_ip = "INET_ATON('$ipaddr')"; 

它结合了“INET_ATON(‘价值$ IPADDR’)”,该名称的SQL函数的不是结果。当一个字符串值被插入到一个整数列时,MySQL将采用任何前导数字的数值,在这种情况下,没有前导数字。所以插入值0。

我建议你使用PHP的内置函数ip2long()

$remote_ip = ip2long($ipaddr); 
mysqli_stmt_bind_param($stmt, 'ss', $email, $remote_ip); 

虽然$remote_ip现在是一个整数,我读过的mysqli有困难结合无符号整数,所以你应该只使用“S”的类型,当你绑定。


回复您的留言:你是对的,因为PHP不支持无符号整数,ip2long()会返回一个负数,如果你的IP地址是128.0.0.0或更大。你可以用sprintf()转换成无符号整数的字符串表示形式:

<?php 

$addr = '192.168.1.1'; 

$ip = ip2long($addr); 
var_dump($ip); 
// int(-1062731519) 

$ip = sprintf("%u", ip2long($addr)); 
var_dump($ip); 
// string(10) "3232235777" 

var_dump(long2ip($ip)); 
// string(11) "192.168.1.1" 
+0

谢谢!事实上,贝克勒尔的解决方案是正确的。 我已经尝试过使用ip2long()。但是有时候它会修改带符号的整数 - 这对于mysql来说效果不好(*推荐的字段类型来存储IP地址是INT(10)UNSIGNED *) 我已经在我的原始文章中发布了解决方法(请参阅IP_ATON ()函数) – invarbrass 2010-05-26 21:42:40