按坐标之间的距离过滤 WordPress 帖子

2023-12-21

我想做的是按两个坐标之间的距离过滤一堆 WordPress 帖子。用户输入的坐标、范围和类别在 URL 中传递,如下所示:

/?cat=0&s=5041GW&range=250&lat=51.5654368&lon=5.071263999999928

然后有一些帖子(并非全部)具有我使用插件高级自定义字段创建的纬度和经度字段。这些是我传递给 get_posts 以获取按类别过滤的帖子的参数:

   $args = array(
        'posts_per_page'   => 24,
        'category'         => $_GET["cat"],
        'orderby'          => 'post_date',
        'order'            => 'DESC',
        'post_type'        => 'adressen',
        'post_status'      => 'publish',
    );

现在我想做的是修改它,以便当实际传递范围和位置时,帖子将被过滤为仅返回位置在用户搜索位置的范围(以公里为单位)内的帖子。我似乎无法找到一个好的解决方案,因为我很难使用 WordPress 及其插件。我真的很感激一个我能理解的解决方案。


这在计算上可能相当昂贵。最简单的方法是获取所有符合条件的帖子,然后循环遍历所有帖子,丢弃指定范围之外的帖子。

由于米和纬度/经度之间没有线性映射,因此出现了困难。这取决于你在地球上的哪个地方。看这个问题 https://stackoverflow.com/questions/8586635/convert-meters-to-latitude-longitude-from-any-point了解详情。这PHPcoord 库 http://www.jstott.me.uk/phpcoord/存在为您进行此计算,但由于我提出的答案稍微近似,我将使用上描述的近似方法这个网站 http://www.movable-type.co.uk/scripts/latlong.html使用半正矢公式 https://en.wikipedia.org/wiki/Haversine_formula.

我将使用以下公式:

  • 要计算两个纬度/经度坐标之间的距离(以公里为单位):

    x = Δλ ⋅ cos φm
    y = Δφ
    d = R ⋅ √(x² + y²)
    

    其中 φ 是以弧度为单位的纬度,λ 是以弧度为单位的经度,R 是地球半径(平均半径 = 6,371km)

  • 要计算给定起始纬度、距离和方位的目的地:

    φ2 = asin( sin φ1 ⋅ cos δ + cos φ1 ⋅ sin δ ⋅ cos θ )
    λ2 = λ1 + atan2( sin θ ⋅ sin δ ⋅ cos φ1, cos δ − sin φ1 ⋅ sin φ2 )
    

    其中 θ 是方位角(从北顺时针方向),δ 是角距离 d/R,d 是行进距离。看atan2 https://en.wikipedia.org/wiki/Atan2.


因此,我们将定义以下辅助函数:

const R = 6371; // km

function distance_between_points_rad($lat1, $lng1, $lat2, $lng2){
    // latlng in radians
    $x = ($lng2-$lng1) * cos(($lat1+$lat2)/2);
    $y = ($lat2-$lat1);
    // return distance in km
    return sqrt($x*$x + $y*$y) * R;
}

function get_destination_lat_rad($lat1, $lng1, $d, $brng){
    return asin( sin($lat1)*cos($d/R) +
                    cos($lat1)*sin($d/R)*cos($brng) );
}

function get_destination_lng_rad($lat1, $lng1, $d, $brng){
    $lat2 = get_destination_lat_rad($lat1, $lng1, $d, $brng);
    return $lng1 + atan2(sin($brng)*sin($d/R)*cos($lat1),
                         cos($d/R)-sin($lat1)*sin($lat2));
}

function get_bounding_box_rad($lat, $lng, $range){
    // latlng in radians, $range in km
    $latmin = get_destination_lat_rad($lat, $lng, $range, 0);
    $latmax = get_destination_lat_rad($lat, $lng, $range, deg2rad(180));
    $lngmax = get_destination_lng_rad($lat, $lng, $range, deg2rad(90));
    $lngmin = get_destination_lng_rad($lat, $lng, $range, deg2rad(270));
    // return approx bounding latlng in radians
    return array($latmin, $latmax, $lngmin, $lngmax);
}

function distance_between_points_deg($lat1, $lng1, $lat2, $lng2){
    // latlng in degrees
    // return distance in km
    return distance_between_points_rad(
        deg2rad($lat1), deg2rad($lng1), deg2rad($lat2), deg2rad($lng2) );
}

function get_bounding_box_deg($lat, $lng, $range){
    // latlng in degrees, $range in km
    return array_map(rad2deg,
        get_bounding_box_rad(deg2rad($lat), deg2rad($lng), $range));
}

(可在ideone中运行 https://ideone.com/pzGjog)

现在,一般流程应为:

  1. 创建一个方形边框,将帖子过滤成一个 几乎正确的很少。这不应该太计算 昂贵,但是一个近似值,可能会留下一些边缘帖子 并包括一些不适合的帖子。
  2. 细化返回的 只向符合要求的人发布帖子。这是一个计算上的 昂贵的过程,因此是第一阶段。排除在外的少数帖子 第一步仍将被排除。边界框可以 可能会做得更大以容纳。

您要使用的查询应包含元信息: 看here http://rudrastyh.com/wordpress/meta_query.html有关其中一些元查询的有用指南

$lat1 = $_GET['lat']; // degrees
$lng1 = $_GET['lng']; // degrees
$range = $_GET['range']; // km

// get the approximate bounding box
$bbox = get_bounding_box_deg($lat1, $lng1, $range);

// query the posts
$args = array(
    'posts_per_page'   => 24,
    'category'         => $_GET["cat"],
    'orderby'          => 'post_date',
    'order'            => 'DESC',
    'post_type'        => 'adressen',
    'post_status'      => 'publish',
    'meta_query' => array(
        'relation' => 'AND',
        array(
            'key' => 'lat',
            'value' => array( $bbox[0], $bbox[1] ),
            'type' => 'numeric',
            'compare' => 'BETWEEN'
        ),
        array(
            'key' => 'lng',
            'value' => array( $bbox[2], $bbox[3] ),
            'type' => 'numeric',
            'compare' => 'BETWEEN'
        )
    )
);
$the_query = new WP_Query( $args );

然后帖子在循环中被过滤:

// Then filter the posts down in the loop
if ( $the_query->have_posts() ) {
    while ( $the_query->have_posts() ) {
        $the_query->the_post();
        $custom_fields = get_post_custom();
        if (isset($custom_fields['lat']) && isset($custom_fields['lng'])){
             $lat2 = $custom_fields['lat'];
             $lng2 = $custom_fields['lng'];
             $dist = distance_between_points_deg($lat1, $lng1, $lat2, $lng2);
             if ($dist <= $range){
                 // post is in range
             } else {
                 // post out of range, discard
             }
        } else {
            // post has no latlng coords
        }
    }
} else {
    // no posts found
}
/* Restore original Post Data */
wp_reset_postdata();

WordPress 代码未经测试,因此如果仍然存在错误,我们深表歉意。不过,总体概念是正确的。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

按坐标之间的距离过滤 WordPress 帖子 的相关文章

  • 重定向至 2 页

    我有一个 PHP 页面 我想先将其重定向到一个页面 例如 google com 然后再重定向到另一个页面 例如 bing com 为此 我使用以下方法 header Location http google com header Locat
  • Laravel 搜索路由和控制器

    我正在构建我的第一个基本 Laravel Web 应用程序 在学习了一些教程之后 这是我自己修改的第一个应用程序 我在路由到控制器然后获取正确的网址时遇到了一些麻烦 理想情况下 此时我应该只有两条路线 and user 在主页上 您可以通过
  • PHP 中的金字塔星号

    请看我的代码 for row var row gt 1 row for j 0 j lt row j echo echo echo nbsp Output 但我需要输出如下 您可能想查看一些字符串函数
  • ImagickException 并显示消息 Postscript delegate 在 MAMP 3.0.5 上失败

    我正在尝试使用 MAMP 3 0 5 将 PDF 转换为 png 文件 我知道我的 PHP 代码可以在我们的 Linux 服务器上正常运行 我在 Mac OSX 10 8 5 上安装了 MAMP 3 0 5 当我运行脚本将 PDF 转换为
  • 不支持的操作数类型

    我正在为网站开发购物车功能 并偶然发现了此错误 致命错误 第 xx 行 中不支持的操作数类型 我认为这可能是因为我正在数组中的变量和值之间执行一些数学运算 我不确定如何对数组中的值执行数学运算 line cost price quantit
  • PHP Foreach数组转表格显示

    我有一个数组 day并希望以表格形式显示该数组 我正在使用 CI Array START EXECUTION gt Array 0 gt 27 OCT 14 1 gt 28 OCT 14 2 gt 29 OCT 14 NUM OF POPU
  • 是 header('Content-Type:text/plain');有必要吗?

    我还没有看到有或没有这个头部信息有什么区别 定义 必要 如果您希望浏览器这样做 这是必要的know文件的类型是什么 PHP 自动设置Content Type标头至text html如果您不覆盖它 那么您的浏览器会将其视为不包含任何 HTML
  • 如何从 PHP 中的两个日期范围中提取每周一和每两周的周一?

    我正在使用臭名昭著的 jQuery UI 的日期选择器 并在我的表单中选择两个日期的范围 首先代表的是starting另一个代表日期end date 我现在需要的是算法 一些提示和方向或帮助者来计算这两个日期之间的每个星期一 例如 star
  • 如何检查 PHP 中的数组?

    我能想到的最好的是 function is array alike array return is array array is object array array instanceof ArrayAccess array instanc
  • PHP 检查 NULL

    这是下面的代码 query mysql query SELECT FROM tablex if result mysql fetch array query if result column NULL print
  • 开源在线 IDE [关闭]

    就目前情况而言 这个问题不太适合我们的问答形式 我们希望答案得到事实 参考资料或专业知识的支持 但这个问题可能会引发辩论 争论 民意调查或扩展讨论 如果您觉得这个问题可以改进并可能重新开放 访问帮助中心 help reopen questi
  • 当用户使用 Internet Explorer 时重定向到新页面

    我使用下面的代码将使用 Internet Explorer 的用户重定向到新页面 但显然代码有问题 因为当我使用 Internet Explorer 时该网站不再加载 这是代码 由于我不知道我做错了什么 如果有人可以发布使用正确编码的正确方
  • 使用 PHP 解析 XML 导航站点地图

    我正在从 XML 文件实现 PHP 站点地图解析器 我做得相对不错 但是 我需要解析器更加动态 我需要实现一个递归函数 它将继续循环找到的每个 child node 一个节点可以在另一个 child node 中包含许多 child nod
  • 在 PHP 中格式化 JSON 格式的文本文件

    所以我得到了一个带有按钮的 HTML 页面 当我单击该按钮时 一个单独的 javascript 文件会向我的 PHP 文件发送 GET 请求 并期望返回 JSON 对象 我的 PHP 读取 JSON 格式的文本文件 并将其转换为 JSONO
  • 分页打印所有数据

    我在打印数据表中具有分页的所有数据时遇到问题 我已经做过研究并在此链接中发现了同样的问题 仅打印 https stackoverflow com questions 468881 print div id printarea div onl
  • WPF ICollectionView 过滤

    我写了一个代码过滤项目在组合框中 我的问题是 你会怎么做 我认为这种带有反射的解决方案可能非常有效slow ICollectionView view CollectionViewSource GetDefaultView newValue
  • codeigniter 分页错误[重复]

    这个问题在这里已经有答案了 在模型 rci model php中 public function record count return this gt db gt count all produk public function fetc
  • argv 和 argc 未定义或为 null

    当我在 construct 中尝试这个时 var dump argc var dump argv var dump SERVER argv 它返回错误 未定义的变量 argc 和未定义的变量 argv 和数组 大小 0 空 当我在全局中声明
  • 以同样的方式根据编号对数组进行洗牌

    我正在运行一个测验制作网站 我希望以打乱的顺序向用户显示问题的答案 我试图avoid如果我要随机打乱答案 则存储向用户呈现答案的顺序 我想以可预测的方式打乱答案 这样我以后就可以用同样的方式重复随机播放 显示结果时 我认为我可以按某个数字对
  • 将静态站点生成器与 php 集成

    我目前正在使用 php 构建一个不需要定期更新的网站 并且我考虑使用静态站点生成器 因为它将具有类似博客的功能 然而 我的网站包含一个将与数据库链接的表单 我遇到的问题是静态站点生成器无法识别和解析 php 我目前正在考虑使用三个静态站点生

随机推荐