From: Andrew Ballard on
On Wed, Jun 23, 2010 at 11:09 AM, Ashley Sheridan
<ash(a)ashleysheridan.co.uk> wrote:
> Out of interest, how does PHP calculate the IP number, as it was my understanding of IP numbers that they can't be negative.
>
> For example, my IP address is 89.243.156.135
> The four parts as binary:
> 01011001
> 11110011
> 10011100
> 10000111
>
> From there, I thought that the binary values were concatenated as if they were a string, and then the decimal value worked out from that, giving, in my case, a value of 1509137543.
>
> How is it possible that PHP can produce negative values from this method? Does it do something else entirely, or is this a case of the integer value overflowing into negative values? (which might explain why the value correctly converts back)
>
> If so, what would be the best method to get the correct value, as abs() obviously isn't it!
>
> Thanks,
> Ash
> http://www.ashleysheridan.co.uk
>
>

It has to do with the storage of the value as a 4-byte integer, as Bob
mentioned. The best way I know of in PHP involves either sprintf
dechex, or pack/unpack. If you use pack/unpack, just be careful with
the endian-ness of the format you choose:

<?php

$x = ip2long('192.168.0.1');
var_dump($x);
// int(-1062731775)

var_dump(long2ip($x));
// string(11) "192.168.0.1"

var_dump(long2ip(abs($x)));
//string(13) "63.87.255.255"

var_dump(sprintf('%u', $x));
// string(10) "3232235521"

var_dump((float) sprintf('%u', $x));
// float(3232235521)

var_dump(pack('L', $x));
// binary value, machine-dependent byte order

var_dump(pack('N', $x));
// binary value, big-endian

var_dump(pack('V', $x));
// binary value, little-endian

var_dump(dechex($x));
// string(8) "c0a80001"

?>

I'm not sure how any of these are best passed along to various
databases, though. I believe something like this should work, as long
as the column defined with a type that will hold the positive value,
such as BIGINT (or, perhaps INT(10) UNSIGNED in MySQL, though I think
I remember having issues with that type).

$sql = sprintf('INSERT INTO `mytable` (`ip_address`) VALUES (%u)',
ip2long($ip));


I do most of my development with SQL Server, so I often just pass the
value as a 4-byte integer (or sometimes even in dotted notation) to a
stored procedure and then let T-SQL do the work.


Andrew