首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 綜合知識

PHP 實現多城市自動切換與手動選擇功能完整指南

     編輯:PHP 綜合知識

前言

在開發面向多城市的網站時,根據訪客 IP 自動定位城市、並提供手動切換功能是常見需求。本文將詳細介紹兩種實現方案:一種基於純真 IP 庫(QQWry.dat)的完整 PHP 實現,另一種利用 JavaScript 配合 PHP 實現的輕量級跳轉方案。文中包含完整代碼示例,涵蓋 IP 獲取、城市匹配、Cookie 記憶、前端交互等關鍵環節。

方案一:基於 QQWry IP 數據庫的完整 PHP 實現

1. 核心 PHP 邏輯

<?php
include_once('./qqwry.php');
$QQWry = new QQWry;

/**
 * 獲取客戶端真實 IP
 */
function get_real_ip() {
    $ip = false;
    if (!empty($_SERVER["HTTP_CLIENT_IP"])) {
        $ip = $_SERVER["HTTP_CLIENT_IP"];
    }
    if (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
        $ips = explode(", ", $_SERVER['HTTP_X_FORWARDED_FOR']);
        if ($ip) {
            array_unshift($ips, $ip);
            $ip = FALSE;
        }
        for ($i = 0; $i < count($ips); $i++) {
            if (!eregi("^(10|172\.16|192\.168)\.", $ips[$i])) {
                $ip = $ips[$i];
                break;
            }
        }
    }
    return $ip ?: $_SERVER['REMOTE_ADDR'];
}

/**
 * 簡單 IP 格式驗證
 */
function is_ip($str) {
    $ip = explode(".", $str);
    if (count($ip) !== 4) return 0;
    foreach ($ip as $ip_addr) {
        if (!is_numeric($ip_addr) || $ip_addr < 0 || $ip_addr > 255) return 0;
    }
    return 1;
}

// 獲取 IP 並查詢城市
$ip = get_real_ip();
$QQWry->QQWry($ip);
$city = $QQWry->Country . $QQWry->Local;

// 針對南京市各區進行標準化映射
$cityMap = [
    '玄武區' => '玄武區',
    '仙林'   => '仙林',
    '秦淮區' => '秦淮區',
    '江寧'   => '江寧',
    '鼓樓'   => '鼓樓',
];
$matched = false;
foreach ($cityMap as $key => $val) {
    if (strpos($city, $key) !== false) {
        $city = $val;
        $matched = true;
        break;
    }
}
if (!$matched) $city = '棲霞';

// 處理手動切換與 Cookie 記憶
if (isset($_GET['chengshi'])) {
    setcookie("cookie_city", $_GET['chengshi'], time() + 86400);
    $city = $_GET['chengshi'];
} elseif (isset($_COOKIE["cookie_city"])) {
    $city = $_COOKIE["cookie_city"];
} else {
    setcookie("cookie_city", $city, time() + 86400);
}
?>

2. 前端 HTML 與交互

<!DOCTYPE html>
<html lang="zh-cn">
<head>
    <meta charset="utf-8"/>
    <link href="css/css.css" rel="stylesheet">
    <script src="js/jquery-1.4.2.min.js"></script>
    <title>城市切換演示</title>
</head>
<body>
    <!-- 城市選擇彈層 -->
    <div class="selCity" id="allCity" style="display: none">
        <div class="area">
            <table><tbody><tr>
                <td><a class="cur" href="show.html">玄武區</a></td>
                <td><a href="show1.html">仙林</a></td>
                <td><a href="show2.html">秦淮區</a></td>
                <td><a href="show3.html">鼓樓</a></td>
                <td><a href="show4.html">江寧</a></td>
                <td><a href="show5.html">棲霞區</a></td>
            </tr></tbody></table>
            <div class="none"><a id="foldin" href="javascript:;">全部</a></div>
        </div>
    </div>

    <!-- 頂部導航 -->
    <div class="header">
        <div class="area">
            <div class="r">
                <div class="topCtiy clear">
                    <ul>
                        <li class="i1"><a href="index.php">全部小區</a></li>
                        <li class="i1"><?php echo $city; ?></li>
                        <li class="i2" id="changeCity">切換城市</li>
                    </ul>
                </div>
            </div>
        </div>
    </div>

    <script>
    jQuery(function($) {
        $("#changeCity").click(function(e) {
            $("#allCity").slideDown(300);
            e.stopPropagation();
            $(this).blur();
        });
        $("#allCity").click(function(e) { e.stopPropagation(); });
        $(document).click(function(e) { if (e.button !== 2) $("#allCity").slideUp(300); });
        $("#foldin").click(function() { $("#allCity").slideUp(300); });
    });
    </script>
</body>
</html>

方案二:獨立 IP 地址解析庫 + JS 跳轉(網友提供)

此方案將 IP 解析邏輯封裝為可復用的 ipCity() 函數,配合 JavaScript 實現頁面級跳轉,適合多子域名或多獨立站點場景。

1. 部署步驟

  1. 下載 QQWry.dat 純真 IP 數據庫,放置於 ipcity/ 目錄。
  2. 在該目錄建立 ipaddress.php,引入下方核心函數。
  3. 在需跳轉的頁面引入 <script src="/ipcity/ipaddress.php"></script>。

2. 核心解析函數(ipaddress.php 核心部分)

<?php
function ipCity($userip) {
    $dat_path = 'QQWry.dat';
    if (!preg_match("/^([0-9]{1,3}\.){3}[0-9]{1,3}$/", $userip)) return 'IP Address Invalid';
    if (!$fd = @fopen($dat_path, 'rb')) return 'IP data file not exists or access denied';

    $ip = explode('.', $userip);
    $ipNum = $ip[0]*16777216 + $ip[1]*65536 + $ip[2]*256 + $ip[3];

    $DataBegin = fread($fd, 4); $DataEnd = fread($fd, 4);
    $ipBegin = implode('', unpack('L', $DataBegin)); if ($ipBegin < 0) $ipBegin += pow(2,32);
    $ipEnd   = implode('', unpack('L', $DataEnd));   if ($ipEnd < 0)   $ipEnd += pow(2,32);
    $ipAllNum = ($ipEnd - $ipBegin) / 7 + 1;

    $BeginNum = 0; $EndNum = $ipAllNum;
    while ($ip1num > $ipNum || $ip2num < $ipNum) {
        $Middle = intval(($EndNum + $BeginNum) / 2);
        fseek($fd, $ipBegin + 7 * $Middle);
        $ipData1 = fread($fd, 4);
        if (strlen($ipData1) < 4) { fclose($fd); return 'File Error'; }
        $ip1num = implode('', unpack('L', $ipData1)); if ($ip1num < 0) $ip1num += pow(2,32);
        if ($ip1num > $ipNum) { $EndNum = $Middle; continue; }

        $DataSeek = fread($fd, 3);
        if (strlen($DataSeek) < 3) { fclose($fd); return 'File Error'; }
        $DataSeek = implode('', unpack('L', $DataSeek.chr(0)));
        fseek($fd, $DataSeek);
        $ipData2 = fread($fd, 4);
        if (strlen($ipData2) < 4) { fclose($fd); return 'File Error'; }
        $ip2num = implode('', unpack('L', $ipData2)); if ($ip2num < 0) $ip2num += pow(2,32);
        if ($ip2num < $ipNum) {
            if ($Middle == $BeginNum) { fclose($fd); return 'No Data'; }
            $BeginNum = $Middle;
        }
    }
    // ... 後續讀取城市名稱邏輯(省略,完整代碼見原文) ...
    fclose($fd);
    return $cityName;
}
?>

3. 前端跳轉邏輯(C 段)

var city = '<?php echo ipCity($xp_UserIp); ?>';
if (city.indexOf("上海市") >= 0) {
    window.location.href = "https://shanghai.demo.com/";
}
// 可繼續擴展更多城市跳轉規則

總結與擴展建議

  • 方案一 適合單一域名下的城市切換,用戶體驗連貫,SEO 友好。
  • 方案二 適合多子域名/多獨立站架構,部署靈活,維護成本低。
  • 兩種方案均依賴 QQWry.dat,建議定期從官方更新以保證準確性。
  • 同理可擴展實現:IP 黑白名單、區域性內容展示、訪問統計分析 等功能。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved