代码之家  ›  专栏  ›  技术社区  ›  Chris

按长/纬度查询自定义帖子类型以查找最近的帖子

  •  0
  • Chris  · 技术社区  · 7 年前

    select 
        locations.*, 
        SQRT(
            69.1*69.1*(latitude - $latitude)*(latitude - $latitude) + 
            53*53*(longitude - $longitude)*(longitude - $longitude)
        ) as distance 
    from locations 
    having distance <= 100 
    order by distance 
    limit 100
    

    我现在正在将网站迁移到Wordpress。我创建了一个名为餐馆的自定义帖子类型,并使用高级自定义字段来记录相同的字段-名称、地址、开放时间和经纬度。我将经度和纬度存储在不同的字段中。

    我可以利用 WP_Query 要查询所有餐厅:

    $query = new WP_Query( array( 'post_type' => 'restaurants' ) );
    

    但是我该如何修改我的 WP\U查询 打电话让我根据所提供的经纬度搜索和排序餐厅?


    3 回复  |  直到 7 年前
        1
  •  1
  •   rank    5 年前

    我找到了一个非常简单且易于实现的解决方案。

    1. 首先,您需要安装此插件: https://mg.wordpress.org/plugins/acf-google-maps-radius-search/

    2. 在函数中。这个的php(!)在第40行中,您必须在变量$address中设置高级自定义字段的名称。

    在acf_gms.class。在这个插件的第163行,您必须在$address变量中再次设置字段的名称。

    4. 现在你必须保存帖子,这些帖子设置了谷歌地图字段和高级自定义字段,因此有一个经度和纬度值。这一点很重要,否则新创建的数据库表(由于插件)中不会包含这些值。

    5.

    应在您的存档中输入以下代码。php文件。请用您的API密钥替换。

    <script type="text/javascript" src="https://maps.googleapis.com/maps/api/js?key=YOURAPIKEY&libraries=places"></script>
    <script>
        function initialize() {
          var input = document.getElementById('location');
          var options = {
            types: ['(regions)'],
        };
          var autocomplete = new google.maps.places.Autocomplete(input, options);
            google.maps.event.addListener(autocomplete, 'place_changed', function () {
                var place = autocomplete.getPlace();
                document.getElementById('lng').value = place.geometry.location.lng();
                document.getElementById('lat').value = place.geometry.location.lat();
            });
        }
        google.maps.event.addDomListener(window, 'load', initialize);
    </script>
    

    <form id="yourform">
        <div>
            <input id="location" type="text" name="location" placeholder="Postcode and place of residence" autocomplete="on" runat="server" />  
            <input type="hidden" id="lng" name="lng" />
            <input type="hidden" id="lat" name="lat" />
        </div> <!-- field -->
        <input type="submit" value="Search nearest" />
    </form>
    

    如果您在id为“location”的输入字段中输入位置,谷歌地图将提供位置建议。当您提交表单时,我们开始的脚本将使用此位置并获得long和lat值。通过隐藏输入,这些值将作为参数(?lng=…&lat=…)发布到URL。

    随着我们插件的运行和新的数据库表,您将获得按距离您输入的位置排序的帖子。

    就是这样。如果你有任何问题,不介意问。

        3
  •  1
  •   Syrex    6 年前

    1. <style>.keepitsecret-keeptitsafe{display:none;}</style> 并为该字段本身提供一个“keepitsecret keepitsafe”类,以便它对前端用户隐藏

    2. 像日常工作一样运行(你知道,这些餐馆多久更换一次位置?)使用lat&数组获取帖子的所有POST\u id;lon应该是这样的:[1=>['lat'=>12123123,'lon'=>12123123132],3=>['lat'=“gt;12123123,'lon'=“gt;12123123132]]并将其作为json存储在先前生成的选项字段中。(提示:检索时,请确保传递false以避免格式化json) get_field('latlon', 'option', false)

    
        $allyourcustomposts = get_posts(['post_type'=>['whateveryourcustompostis'], 'posts_per_page'=> -1]);
        foreach($allyourcustomposts as $post) {
            $lat = get_field('lat', $post->ID);
            $lon = get_field('lon', $post->ID);
            if($lat && $lon && $lat != '' && $lon != '') {
                $savior[$post->ID] = ['lat'=>$lat,'lon'=>$lon];
            }
        }
        if(count($savior) > 0) {
            $json = json_encode($savior);
            update_field('field_5b04b0544d603', $json, 'option');
            @file_put_contents('savior.json', $json);
        }
    
    1. 创建一个函数,使用可选的$distance=0参数查找两个位置之间的距离。

    2. asort数组,然后array\u键按顺序获取所有post id

    最后,在wp\u查询到$args['post\uu in']=$finalspostids时,

    如果需要按$finalpostids中的顺序排序,$args['orderby]=“post\u in”

    一点点启动代码:

    
    
        function orderByNearby($lat, $lon, $arrayOfLatLonPosts, $distance = 0) {
            $orderedIds = [];
            if($lat != 0 && $lon != 0 && $arrayOfLatLonPosts && count($arrayOfLatLonPosts) > 0) {
                foreach($arrayOfLatLonPosts as $post_id => $arrayOfLatLonPost) {
                    $dist = @closeEnough($arrayOfLatLonPost->lat, $arrayOfLatLonPost->lon, $lat, $lon);
                    if($distance > 0) {
                        if($dist  0) {
            asort($ids);
            $args['post__in'] = array_keys($ids);
            $args['orderby'] = 'post__in';
        } else {
            $args['s'] = 'this is hilariously monstreous stupendous name search that will never and probably will ever match!!! so blah blah blah blah blah';
        }
    
    

    因此,当您传递$distance变量时,有时会得到0个结果,在这种情况下,只需传递非常长的搜索文本即可返回空。

    祝你好运