在WordPress中根据地理位置信息查询附近用户发布的相关内容

在某些应用场景下,我们可能需要依据当前位置来查找周边其他用户发布的内容。实现这一功能的一种方法是通过自定义代码结合特定的数据结构完成。以下是详细的步骤与代码示例

数据表设计

首先,我们需要创建一个名为wp_post_locations的新数据表用于存储位置信息。该数据表将包含每个帖子的位置数据,使得基于位置的搜索成为可能。请确保设计的数据表结构能够有效地支持经纬度等地理信息的存储,以便后续查询操作。

查询代码实现

接下来,使用以下代码片段作为基础来实现基于位置信息查询附近内容的功能。请注意,实际应用时您可能需要根据自己的数据库结构和需求调整这部分代码。

CREATE TABLE wp_post_locations(
            id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
            post_id BIGINT UNSIGNED NOT NULL,
            latitude DECIMAL(10,8) NOT NULL,
            longitude DECIMAL(11,8) NOT NULL,
            city VARCHAR(255) NULL,
            region VARCHAR(100) NULL,
            country VARCHAR(100) NULL,
            address VARCHAR(255) NULL,
            ip varchar(45) NOT NULL,
            created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
            INDEX idx_post_id (post_id),
            INDEX idx_geolocation (latitude, longitude),
            INDEX idx_city_region_country (city, region, country),
            FOREIGN KEY (post_id) REFERENCES wp_posts(ID) ON DELETE CASCADE ON UPDATE CASCADE
) $charset_collate;

查询代码如下:

$latitude = isset($params['latitude']) ? floatval($params['latitude']) : null;
$longitude = isset($params['longitude']) ? floatval($params['longitude']) : null;
if ($latitude !== null && $longitude !== null) {
    $post_ids = [];
    $radius = 100; // 半径100KM
    $earth_radius = 6371; // 地球半径,单位:公里
    $min_lat = $latitude - rad2deg($radius / $earth_radius);
    $max_lat = $latitude + rad2deg($radius / $earth_radius);
    $max_lon = $longitude + rad2deg(asin($radius / $earth_radius) / cos(deg2rad($latitude)));
    $min_lon = $longitude - rad2deg(asin($radius / $earth_radius) / cos(deg2rad($latitude)));
    $table_name = $this->database->prefix . 'post_locations';
    $query = $this->database->prepare("
                SELECT post_id, 
                    (6371 * acos(
                        cos(radians(%f)) * cos(radians(latitude)) *
                        cos(radians(longitude) - radians(%f)) +
                        sin(radians(%f)) * sin(radians(latitude))
                    )) AS distance
                FROM $table_name
                WHERE latitude BETWEEN %f AND %f
                AND longitude BETWEEN %f AND %f
                AND (
                    6371 * acos(
                        cos(radians(%f)) * cos(radians(latitude)) *
                        cos(radians(longitude) - radians(%f)) +
                        sin(radians(%f)) * sin(radians(latitude))
                    ) <= %f
                )
                ORDER BY distance ASC
    ", $latitude, $longitude, $latitude, $min_lat, $max_lat, $min_lon, $max_lon, $latitude, $longitude, $latitude, $radius);
    $post_distances = $this->database->get_results($query, ARRAY_A);
    if ($this->database->last_error) {
        return new \WP_REST_Response('查询过程中发生错误: ' . esc_html($this->database->last_error), 500);
    }
    if ($this->database->last_error) {
        return new \WP_REST_Response('查询过程中发生错误: ' . esc_html($this->database->last_error), 500);
    }
    if (!empty($post_distances)) {
        $post_ids = array_column($post_distances, 'post_id');
        $distance_map = array_column($post_distances, 'distance', 'post_id');
    } else {
        return new \WP_REST_Response([], 200);
    }
    $args['post__in'] = $post_ids;
}
+2

发表回复