我有一个网站,允许用户输入他们的邮政编码,然后他们看到附近的餐馆。我将餐厅存储在MySQL表中,每行包含餐馆名称,地址,营业时间以及经度和纬度。
当用户输入邮政编码时,我使用Google API将邮政编码转换为经度和纬度,然后使用此SQL查询......
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。我创建了一个名为restaurants的自定义帖子类型,并使用高级自定义字段记录相同的字段 - 名称,地址,开放时间和经度和纬度。我将经度和纬度存储在不同的字段中。
我可以利用WP_Query
查询所有餐馆:
$query = new WP_Query( array( 'post_type' => 'restaurants' ) );
但是如何修改我的WP_Query
电话,以便我可以通过接近所提供的经度和纬度来搜索和分类餐馆?
答案 0 :(得分:1)
首先wordpress将你的自定义帖子存储在wp_posts表中,而acf字段存储在wp_post_meta表中,所以你必须以某种方式将它们与sql连接起来。如果我理解你的正确,你可以使用wpdb类,它允许你自己的SQL查询。 https://codex.wordpress.org/Class_Reference/wpdb
答案 1 :(得分:1)
我认为最好的选择是
在主题选项中创建一个文本区域的acf字段,给它提示<style>.keepitsecret-keeptitsafe{display:none;}</style>
,并为该字段本身提供一个&#34; keepitsecret-keeptitsafe&#34;所以它隐藏在前端用户
像每天的cronjob一样运行(这些餐馆多久更换一次locatoins,你知道吗?)来获取帖子的所有POST_ID,其中包含一个lat&amp; lon数组,它应该是这样的:[1 =&gt; ; [&#39; lat&#39; =&gt; 12123123,&#39; lon&#39; =&gt; 12123123132],3 =&gt; [&#39; lat&#39; =&gt; 12123123,&#39 ; lon&#39; =&gt; 12123123132]]并将其存储为先前创建的选项ACField中的json。 (提示:当你检索时,确保传递假以避免格式化你的json)get_field('latlon', 'option', false)
//作为bakcup,如果你想要保存到文件
$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);
}
使用可选的$ distance = 0参数创建一个查找2个位置之间距离的函数。
现在当你搜索时,迭代来自存储的POST_ID =&gt; lat&amp; lon数组的所有帖子,保存一个单独的$ finals数组[post_id] = distance
对数组进行asort,然后使用array_keys来获取订单中的所有帖子ID
最后在你的wp_query到$ args [&#39; post__in&#39;] = $ finalspostids,
如果您需要按照$ finalpostids中的订单进行订购,则$ args [&#39; orderby&#39;] =&#39; post__in&#39;
一些初学者代码:
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结果,只要传递极长的搜索文本就可以返回空。
PS。第一次在这里回答问题,可怕的编辑是碉堡!!!
祝你好运。答案 2 :(得分:1)
VA79是正确的,这将非常复杂,需要执行sql连接和操作。
我找到了一个非常简单且易于实现的解决方案。
1。 首先,您需要安装此插件: https://mg.wordpress.org/plugins/acf-google-maps-radius-search/
2。 在第40行的this(!)插件的functions.php中,您必须在变量$ address中设置高级自定义字段的名称。
3。 在第163行的此插件的acf_gms.class.php中,您必须在$ address变量中再次设置字段名称。
4。 现在,您必须保存设置了“ Google地图字段”表单“高级自定义字段”并因此具有经度和纬度值的帖子。这很重要,否则新创建的数据库表(由于插件)将没有值。
5。 保存后,您的数据库中将有一个新表,其中包含“职位ID”,“长整数和经度值”。多亏了该插件,太棒了。
我现在假设您要在帖子存档页面上拥有表单字段,您可以在其中输入地址,并按顺序输出帖子,其中先显示最近的帖子,然后显示下一个最近的帖子,再依次显示以此类推。您想找到最近的,所以我想这就是您要寻找的。 p>
以下代码应输入到archive.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>
如您所见,我们正在从表单字段中获取位置,long和lat值。因此,表单看起来像这样,可以放在php归档文件中。
<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”的输入字段,则Google地图会建议位置。提交表单时,我们开始使用的脚本将使用此位置并获取long和lat值。使用隐藏的输入,此值将作为参数(?lng = ...&lat = ...)发布到URL。
运行我们的插件并使用新的数据库表后,您将按到您输入的位置的距离获得排序的帖子。
就是这样。如果您有任何疑问,不要介意。