DEMO:
http://www.betadir.com/clases/geo.class.php
Ultima actualizacion incluye un metodo para re-seleccionar base de datos si habia una previa seleccionada: close()
Tengan en cuenta que el nombre de la DB de geolocalizacion esta dentro de la clase misma y Uds deberian cambiarlo.
Código PHP:
<?php
include "my/config.php";
class Geo {
private $con;
public $selected;
private $localhost;
private $data = array(
// DB DATA
'host','user','pass',
// GEO
'ip'=>null, 'locId'=>null,'country'=>null,'region'=>null,'city'=>null,
'postalCode'=>null,'latitude'=>null,'longitude'=>null,
'metroCode'=>null,'areaCode'=>null,
'countryName'=>null,'lan'=>null);
public function Geo(){
}
public function __set($name, $value) {
//echo "Estableciendo '$name' a '$value'\n";
$this->data[$name] = $value;
}
public function __get($name) {
//echo "Consultando '$name'\n";
if (array_key_exists($name, $this->data)) {
return $this->data[$name];
}
$trace = debug_backtrace();
trigger_error(
'Propiedad indefinida mediante __get(): ' . $name .
' en ' . $trace[0]['file'] .
' en la línea ' . $trace[0]['line'],
E_USER_NOTICE);
return null;
}
/** Desde PHP 5.1.0 */
public function __isset($name) {
//echo "¿Está definido '$name'?\n";
return isset($this->data[$name]);
}
/** Desde PHP 5.1.0 */
public function __unset($name) {
//echo "Eliminando '$name'\n";
unset($this->data[$name]);
}
private function connect(){
$this->con = mysql_connect($this->host,$this->user,$this->pass) or die ("Error conectando a mysql en {$_SERVER['PHP_SELF']}");
$res = mysql_query("SELECT DATABASE()");
if (mysql_num_rows($res)==1){
$row = mysql_fetch_array ($res);
$this->selected = $row[0];
}
mysql_select_db('videosbu_geo') or die ("Error seleccionando base en {$_SERVER['PHP_SELF']}");
}
public function close(){
if ( (isset($this->selected)) AND (!$this->localhost) ){
mysql_select_db($this->selected) or die ("Error seleccionando base en {$_SERVER['PHP_SELF']}");
}
}
public function IPremote(){
$this->ip = $_SERVER['REMOTE_ADDR'];
}
public function doit($also_lan_and_countryName=true){
if ($this->ip == '127.0.0.1'){
$this->data['country']='xx';
$this->data['countryName']='localhost';
$this->data['city']='localhost';
$this->localhost = true;
return true;
// fin del flujo
}
$this->connect();
$ipv4 = toIPv4($this->ip);
$sql = "
SELECT cl.country, cl.region, cl.city, cl.postalCode, cl.latitude, cl.longitude, cl.metroCode, cl.areaCode FROM citylocation cl
INNER JOIN
(SELECT locId FROM cityblocks WHERE ($ipv4 > startIpNum AND $ipv4 < endIpNum) ORDER BY startIpNum DESC LIMIT 1)
t1 ON cl.locid = t1.locId";
$res = mysql_query($sql) OR die(mysql_error());
$cant_rows = mysql_num_rows($res);
if ($cant_rows==1){
$this->data = mysql_fetch_assoc($res);
if ($also_lan_and_countryName){
// recupero nombre de pais y lengua
$sql = "SELECT lan,name FROM countries WHERE id='{$this->country}'";
$res = mysql_query($sql) OR die(mysql_error());
$row = mysql_fetch_array($res);
$this->lan = $row['lan'];
$this->countryName = $row['name'];
}
// retorno exito
return true;
}else{
// no hay resultados
return false;
}
}
} // end class
function toIPv4 ($dotted){
if (( $lngIP = ip2long ( $dotted)) < 0 ){
$lngIP += 4294967296 ;
}
return $lngIP;
}
function set_geo_vars(){
session_start();
global $db_info;
// pregunto si ya busque geolocalizacion para no repetir la busqueda en la DB
if (!isset($_SESSION['geo_runned'])){
$loc= new geo();
$loc->host = $db_info['host'];
$loc->user = $db_info['user'];
$loc->pass = $db_info['pass'];
$loc->IPremote();
$succ = $loc->doit();
$loc->close(); // devuelve a la DB antes seleccionada (si la hay)
$_SESSION['geo_runned'] = 1;
if ($succ){
$_SESSION['country'] = $loc->country;
$_SESSION['countryname'] = $loc->countryName;
$_SESSION['city'] = $loc->city;
$_SESSION['latitude'] = $loc->latitude;
$_SESSION['longitude'] = $loc->longitude;
$_SESSION['lan_from_geo'] = $loc->lan;
}else{
return false;
//echo 'No se encontro info para esa IP';
}
}
return true;
}
?>
La funcion set_geo_vars() la utilizo para dejar como variables de session los datos de geolocalizacion y evitar calcularlos antes y despues de que un usuario se registre. Al menos, yo necesite eso.
Tablas:
Cita: CREATE TABLE IF NOT EXISTS `cityblocks` (
`startIpNum` bigint(20) NOT NULL,
`endIpNum` bigint(20) NOT NULL,
`locId` bigint(20) NOT NULL,
PRIMARY KEY (`startIpNum`),
UNIQUE KEY `locId` (`startIpNum`,`endIpNum`,`locId`),
KEY `endIpNum` (`endIpNum`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
CREATE TABLE IF NOT EXISTS `citylocation` (
`locId` bigint(20) NOT NULL,
`country` varchar(2) NOT NULL,
`region` varchar(2) NOT NULL,
`city` varchar(50) NOT NULL,
`postalCode` varchar(10) NOT NULL,
`latitude` int(11) NOT NULL,
`longitude` int(11) NOT NULL,
`metroCode` int(11) NOT NULL,
`areaCode` int(11) NOT NULL,
PRIMARY KEY (`locId`),
UNIQUE KEY `locId` (`locId`,`country`,`region`,`city`,`postalCode`,`l atitude`,`longitude`,`metroCode`,`areaCode`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
Para utilizarla es asi:
Código PHP:
<?php
Include "geo.class.php"; // tu path
$loc= new geo();
$loc->host = $db_info['host'];
$loc->user = $db_info['user'];
$loc->pass = $db_info['pass'];
//$loc->IPremote();
$loc->ip = '148.210.232.247';
$succ = $loc->doit();
if ($succ){
echo "Codigo de pais: ".$loc->country.'<br/>';
echo "Nombre de pais: ".$loc->countryName.'<br/>';
echo "Ciudad: ".$loc->city.'<br/>';
echo "Latitud: ".$loc->latitude.'<br/>';
echo "Longitud: ".$loc->longitude.'<br/>';
echo "Lengua oficial: ".$loc->lan.'<br/>';
}else{
echo 'No se encontro info para esa IP';
}
?>
Un abrazo y recuerden de la
DEMO