note 79890 modified in function.ip2long by danbrown
| From: | danbrown@php.net | Date: | Fri, 05 Dec 2008 13:34:03 +0000 |
| Subject: | note 79890 modified in function.ip2long by danbrown | ||
| References: | 1 | Groups: | php.notes |
| Request: | Send a blank email to php-notes+get-147687@lists.php.net to get a copy of this message | ||
Thanks to sealbreaker for the conversion method. I'd seen <?php (ip2long($ip) &
0x7FFFFFFF) + 0x80000000 ?> before, but noticed it didn't work on all ips. You've
discovered why. :)
In case anyone is wondering what sealbreaker means by obtaining an "integer value", s/he
means an unsigned int, vs the signed version ip2long provides. Well, technically this conversion
will sometimes give you a float since php's integer type is signed.
The good news is that long2ip will correctly handle converting these signed versions back into ips.
So, to get an unsigned version of an ip (ie, always >= 0):
<?php
$ip = '127.0.0.1';
// may return a php int or float
$signed = substr($ip, 0, 3) > 127 ? ((ip2long($ip) & 0x7FFFFFFF) + 0x80000000) :
ip2long($ip);
// will return a string version
$signed2 = sprintf('%u', ip2long($ip));
var_dump($signed, $signed2, long2ip($signed), long2ip($signed2));
?>
P.S.: If you're storing IPs in MySQL, there is NO POINT in converting to these unsigned values
to place in an INT UNSIGNED column. Just use an INT SIGNED column, and directly use the result from
ip2long. The only reason you should really need to force your ip2long result into its unsigned
version is if you need to compare them with another source that uses unsigned (ie: some IP database
lookup utils use unsigned).
--was--
Thanks to sealbreaker for the conversion method. I'd seen <? (ip2long($ip) & 0x7FFFFFFF)
+ 0x80000000 ?> before, but noticed it didn't work on all ips. You've discovered why.
:)
In case anyone is wondering what sealbreaker means by obtaining an "integer value", s/he
means an unsigned int, vs the signed version ip2long provides. Well, technically this conversion
will sometimes give you a float since php's integer type is signed.
The good news is that long2ip will correctly handle converting these signed versions back into ips.
So, to get an unsigned version of an ip (ie, always >= 0):
<?
$ip = '127.0.0.1';
// may return a php int or float
$signed = substr($ip, 0, 3) > 127 ? ((ip2long($ip) & 0x7FFFFFFF) + 0x80000000) :
ip2long($ip);
// will return a string version
$signed2 = sprintf('%u', ip2long($ip));
var_dump($signed, $signed2, long2ip($signed), long2ip($signed2));
?>
P.S.: If you're storing IPs in MySQL, there is NO POINT in converting to these unsigned values
to place in an INT UNSIGNED column. Just use an INT SIGNED column, and directly use the result from
ip2long. The only reason you should really need to force your ip2long result into its unsigned
version is if you need to compare them with another source that uses unsigned (ie: some IP database
lookup utils use unsigned).
http://php.net/manual/en/function.ip2long.php