当前位置:首页 > PHP

php实现lbs实现商品筛选

2026-02-15 03:26:56PHP

PHP实现LBS商品筛选的方法

数据库设计

在MySQL中存储商品信息时需包含经纬度字段(如latitudelongitude),推荐使用POINT空间数据类型。创建表时可添加空间索引加速查询:

CREATE TABLE products (
    id INT PRIMARY KEY,
    name VARCHAR(255),
    location POINT NOT NULL,
    SPATIAL INDEX(location)
);

距离计算

使用Haversine公式计算两点间距离(单位:公里):

function getDistance($lat1, $lon1, $lat2, $lon2) {
    $earthRadius = 6371;
    $dLat = deg2rad($lat2 - $lat1);
    $dLon = deg2rad($lon2 - $lon1);
    $a = sin($dLat/2) * sin($dLat/2) + 
         cos(deg2rad($lat1)) * cos(deg2rad($lat2)) * 
         sin($dLon/2) * sin($dLon/2);
    $c = 2 * atan2(sqrt($a), sqrt(1-$a));
    return $earthRadius * $c;
}

MySQL空间查询

对于MySQL 5.7+版本,可直接使用ST_Distance_Sphere函数:

php实现lbs实现商品筛选

SELECT 
    id, 
    name,
    ST_Distance_Sphere(location, POINT(:user_lon, :user_lat)) / 1000 AS distance_km
FROM 
    products
WHERE 
    ST_Distance_Sphere(location, POINT(:user_lon, :user_lat)) <= :radius_km * 1000
ORDER BY 
    distance_km;

Redis GEO优化

对高频访问场景可使用Redis GEO数据结构:

$redis->geoAdd('products:locations', $longitude, $latitude, $productId);
$results = $redis->geoRadius('products:locations', $userLon, $userLat, $radius, 'km');

分页处理

结合距离筛选时需注意分页逻辑,建议先获取符合条件的所有ID,再分页查询详细信息:

php实现lbs实现商品筛选

$page = $_GET['page'] ?? 1;
$perPage = 10;
$offset = ($page - 1) * $perPage;

$stmt = $pdo->prepare("
    SELECT SQL_CALC_FOUND_ROWS p.*
    FROM products p
    WHERE ST_Distance_Sphere(location, POINT(?, ?)) <= ? * 1000
    LIMIT ? OFFSET ?
");
$stmt->execute([$userLon, $userLat, $radius, $perPage, $offset]);

性能优化

  1. 确保latitudelongitude字段建立复合索引
  2. 对固定区域商品可先进行地理边界框预筛选
  3. 使用缓存存储热门区域的查询结果
  4. 考虑使用Elasticsearch的geo_point类型实现高级搜索

前端交互

通过浏览器获取用户位置后传递给后端:

navigator.geolocation.getCurrentPosition(position => {
    const {latitude, longitude} = position.coords;
    // 发送AJAX请求到PHP后端
});

完整示例

后端接口处理示例:

// 获取前端传递的经纬度和半径
$userLat = $_GET['lat'];
$userLon = $_GET['lon'];
$radius = $_GET['radius'] ?? 5; // 默认5公里

$products = $pdo->prepare("
    SELECT id, name, 
           ST_Distance_Sphere(location, POINT(?, ?)) / 1000 AS distance
    FROM products
    WHERE ST_Distance_Sphere(location, POINT(?, ?)) <= ? * 1000
    ORDER BY distance
")->execute([$userLon, $userLat, $userLon, $userLat, $radius]);

header('Content-Type: application/json');
echo json_encode($products->fetchAll());

标签: 商品php
分享给朋友:

相关文章

vue实现商品列表

vue实现商品列表

Vue实现商品列表的方法 使用Vue实现商品列表需要结合数据绑定、组件化和状态管理。以下是实现商品列表的几种常见方法: 基础数据绑定实现 在Vue组件中定义商品数据数组,使用v-for指令循环渲染商…

php实现文件下载

php实现文件下载

PHP实现文件下载的方法 通过PHP实现文件下载功能,可以采用多种方式,以下是几种常见的实现方法: 使用header()函数强制下载 设置HTTP头信息,强制浏览器下载文件而非直接打开: $fi…

php 实现文件下载

php 实现文件下载

实现文件下载的基本方法 使用 PHP 实现文件下载的核心是通过设置 HTTP 头部信息,强制浏览器将文件作为附件下载而非直接显示。以下是一个基础实现示例: $file_path = '/path/t…

php怎么实现登录功能

php怎么实现登录功能

数据库准备 创建用户表存储登录信息,通常包括用户名、密码(需加密)等字段。示例SQL: CREATE TABLE users ( id INT AUTO_INCREMENT PRIMARY…

php 实现评论

php 实现评论

实现 PHP 评论功能 数据库设计 创建数据库表存储评论数据,通常包含以下字段: id:评论唯一标识 user_id:用户ID content:评论内容 created_at:评论时间 paren…

php 链表实现

php 链表实现

在 PHP 中实现链表可以通过类来模拟链表节点(Node)和链表(LinkedList)结构。以下是链表的完整实现示例,包含基础操作如插入、删除、遍历等。 链表节点类(Node) 链表的基本单元是节…