PHP / mysqli:使用mysqli_stmt_bind_param()插入IP地址

时间:2010-05-26 21:30:02

标签: php mysql ip ip-address

我有一个数据库表,其中包含一个无符号整数字段,用于存储访问者的IP地址:

`user_ip` INT(10) UNSIGNED DEFAULT NULL,

以下是试图存储IP地址的PHP代码片段:

$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。我已经尝试将$ ip_addr变量作为整数和& mysqli_bind_param()中的字符串 - 无济于事。

似乎问题在于参数化插入。

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

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

我在这里做错了什么?

提前致谢!

2 个答案:

答案 0 :(得分:3)

我认为它应该是这样的:

$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的参数应该是要插入的实际值,而不是任何函数。

答案 1 :(得分: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不支持无符号整数,如果你的IP地址是128.0.0.0或更高,ip2long()将返回一个负数。您可以使用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"