PHP调用ip_info()报未定义函数错误及IP获取访客归属地用法问题
报错原因
ip_info() 并非PHP官方内置函数,你看到的用法示例是其他开发者自定义封装的函数,或是特定第三方扩展提供的函数,当前运行环境没有引入该函数的定义文件,也没有安装对应扩展,因此调用时会触发未定义函数的致命错误。
实现IP归属地查询的可用方案
方案1:调用公开IP查询接口(无需额外配置,适合轻量场景)
无需在本地部署数据库,直接通过HTTP请求第三方IP查询服务获取结果,示例实现如下:
<?php // 封装获取访客真实IP的方法 function get_real_ip() { $ip = ''; if (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) { $ip = trim(explode(',', $_SERVER['HTTP_X_FORWARDED_FOR'])[0]); } elseif (!empty($_SERVER['HTTP_CLIENT_IP'])) { $ip = $_SERVER['HTTP_CLIENT_IP']; } else { $ip = $_SERVER['REMOTE_ADDR']; } // 过滤保留地址、私有地址等无效公网IP if (!filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE)) { return '8.8.8.8'; // 本地测试时可替换为任意公网IP } return $ip; } // 调用IP查询接口获取结果,接口地址可替换为任意合规的IP查询服务 $visitor_ip = get_real_ip(); $query_url = "http://ip-api.com/json/{$visitor_ip}?lang=zh-CN"; $response = file_get_contents($query_url); $result = json_decode($response, true); if ($result['status'] === 'success') { echo "国家:{$result['country']}\n"; echo "国家代码:{$result['countryCode']}\n"; echo "省份:{$result['regionName']}\n"; echo "城市:{$result['city']}\n"; } ?>
方案2:本地部署GeoIP数据库(无需调用外网接口,性能更高)
适合高并发场景,不需要依赖外部接口可用性,可使用MaxMind提供的免费GeoLite2数据库实现:
- 第一步通过Composer安装依赖:
composer require maxmind/geoip2 - 第二步下载免费的GeoLite2-City数据库文件到项目目录
- 调用示例:
<?php require 'vendor/autoload.php'; use GeoIp2\Database\Reader; // 替换为你自己的数据库文件存放路径 $geo_reader = new Reader(__DIR__ . '/GeoLite2-City.mmdb'); $visitor_ip = get_real_ip(); try { $record = $geo_reader->city($visitor_ip); echo "国家:{$record->country->name}\n"; echo "国家代码:{$record->country->isoCode}\n"; echo "省份:{$record->mostSpecificSubdivision->name}\n"; echo "城市:{$record->city->name}\n"; } catch (Exception $e) { echo "归属地查询失败:" . $e->getMessage(); } ?>
方案3:封装兼容原示例的ip_info()函数
如果需要沿用你之前看到的ip_info()调用方式,可将上述逻辑封装为自定义函数,原业务代码不需要修改即可正常运行。
内容的提问来源于stack exchange,提问作者Swargaraj Bhowmik
相关产品推荐
相关产品推荐

