说明:我正在创建一个IP类,该类首先找到访问者的IP地址(使用$_SERVER['REMOTE_ADDR']
或getenv('REMOTE_ADDR')
),确保'如果是有效的IP,请将数据(IPv4或IPv6)设置为数据成员,然后返回IP地址,如果是SQL查询,则返回SQL参数(请参阅{{1}以下函数可用于返回)。
问题:如果服务器没有运行MySQL 5.6.3+,如何将存储在数据库表(createQueryParam()
)中的IPv6二进制文件转换为字符串?
对于IPv6以及未运行MySQL 5.6.3+的系统,我想返回MySQL功能,还是可以进行按位操作?否则,我必须在varbinary(16)
之后再使用PHP的inet_ntop()函数进行另一次调用,而我真的不愿意这样做。
PHP:
findIP()
示例:
访客的IP是2001:cdba:0000:0000:0000:0000:3257:9652
用于INSERT的MySQL或PHP函数:
class IP
{
protected $ip=NULL;
protected $ip_version=NULL;
/**
* setIP
*
* Sets the data member $ip.
*
* @param $ip
* @access protected
*/
protected function setIP($ip)
{
# Check if the passed value is empty.
if(!empty($ip))
{
# Clean it up.
$ip=$ip;
}
else
{
# Explicitly set it to NULL.
$ip=NULL;
}
# Set the data member.
$this->ip=$ip;
} #==== End -- setIP
/**
* setIPVersion
*
* Sets the data member $ip_version.
*
* @param $ip_version
* @access protected
*/
protected function setIPVersion($ip_version)
{
# Set the Validator instance to a variable.
$validator=Validator::getInstance();
# Check if the passed value is NULL.
if($ip_version!==NULL)
{
# Clean it up.
$ip_version=trim($ip_version);
# Check if the passed value is an integer.
if($validator->isInt($ip_version)===TRUE)
{
# Explicitly make it an integer.
$ip_version=(int)$ip_version;
}
else
{
throw new Exception('The passed IP version was not a number!', E_RECOVERABLE_ERROR);
}
}
else
{
# Explicitly set it to NULL.
$ip_version=NULL;
}
# Set the data member.
$this->ip_version=$ip_version;
} #==== End -- setIPVersion
/**
* getIP
*
* Returns the data member $ip.
*
* @access public
*/
public function getIP()
{
return $this->ip;
} #==== End -- getIP
/**
* getIPVersion
*
* Returns the data member $ip_version.
*
* @access public
*/
public function getIPVersion()
{
return $this->ip_version;
} #==== End -- getIPVersion
/**
* createQueryParam
*
* Determines what MySQL function should be used based on MySQL version.
*
* @param $ip The visitor's IP address or ip field in database table.
* @access public
* @return string
*/
public function createQueryParam($ip, $select_query=FALSE)
{
# Set the Database instance to a variable.
$db=DB::get_instance();
# Get the database client version.
$client_version=$db->client_version;
# If the client version is 5.6.3+ use INET6_ATON.
if($client_version>=50603)
{
# If this is not for a select query.
if($select_query===FALSE)
{
return " INET6_ATON('".$ip."')";
}
# This is for a select query.
return ' INET6_NTOA(`'.$ip.'`)';
}
# Else we assume PHP has IPv6 support and use PHP's inet_pton() to convert the IP to a binary.
else
{
# If this is not for a select query.
if($select_query===FALSE)
{
# If IPv4 then use MySQL function.
if($this->getIPVersion()==4)
{
return " INET_ATON('".$ip."')";
}
else
{
# Supports IPv4 & IPv6 (if PHP has IPv6 supprot enabled).
return inet_pton($ip);
}
}
# NOTE: How to handle select queries for IPv6 if MySQL version is less then 5.6.3?
# Can a MySQL bitwise operation be used here?
# IPv4 Only.
//return ' INET_NTOA(`'.$ip.'`)';
# For IPv6 I could use PHP's inet_ntop() but we can't return it here.
}
} #=== End -- createQueryParam
/**
* findIP
*
* Returns the IP of the visitor.
* Throws an error if the IP address is not valid.
*
* @param bool $for_sql_query Convert IP addresss to binary for database.
* @access public
* @return string
*/
public function findIP($for_sql_query=FALSE)
{
# Get the visitor's IP addreess.
# Use $_SERVER over getenv() since it's more server compatible.
# If $_SERVER['REMOTE_ADDR'] is empty, use getenv().
$ip=$ip=(!empty($_SERVER['REMOTE_ADDR'])) ? $_SERVER['REMOTE_ADDR'] : getenv('REMOTE_ADDR');
# Check if the IP Address is valid.
# Throws an error if the IP is not valid.
if($this->ipValid($ip)===TRUE)
{
# If we need to create the IP to a binary.
if($for_sql_query===TRUE)
{
# Convert the visitor's IP to a binary.
$ip=$this->createQueryParam($ip);
}
# Set the IP address to the data member.
$this->setIP($ip);
}
# Return the data member.
return $this->getIP();
} #==== End -- findIP
/**
* ipValid
*
* Will determine if a given IP address is valid or not.
* Will set the version of the IP address to the $ip_version data member.
* Throws an error if the IP is not valid.
*
* @access public
* @param $ip The IP address to validate.
* @return boolean
*/
public function ipValid($ip)
{
# Detect if it is a valid IPv4 Address
if(filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4))
{
# This is an IPv4 address.
$version=4;
}
# Detect if it is a valid IPv6 Address
elseif(filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6))
{
# This is an IPv6 address.
$version=6;
}
if(isset($version))
{
$this->setIPVersion($version);
return TRUE;
}
else
{
throw new Exception('The IP address was not valid!', E_RECOVERABLE_ERROR);
}
return FALSE;
} #==== End -- ipValid
} #=== End IP class.
用于SELECT的MySQL或PHP函数:
# Create a new IP object.
$ip_obj=new IP();
# This is for an SQL query.
$ip=$ip_obj->findIP(TRUE);
# On systems not running MySQL 5.6.3+ it uses PHP's inet_pton().
# $ip = ͺ2W�R
$sql='INSERT INTO `ip_log` (`ip`) VALUES ('.$ip.')';
# $sql = INSERT INTO `ip_log` (`ip`) VALUES ( ͺ2W�R);