我在WordPress中有很多帖子。这些帖子属于“餐馆”类别。每个帖子都有一个自定义的元键/值,如下所示:
$post_geocode = get_post_meta($post->ID, 'geocode', true);
// $post_geocode = '34.0510613,-118.244705'
您必须登录WordPress才能使用我的网站,因此每个用户都有为其存储的地理编码,如下所示:
$user_geocode = get_user_meta( $user->ID, 'geocode', true );
// $user_geocode = '34.043925,-118.2424291'
因此,我希望能够获得帖子并对其进行排名,以便与用户所在位置相近。
理想情况下,它会使用WP Query类。但我很乐意在需要时更改地理编码的存储方式。
最佳答案如下:
// This is how I manage the type of restaurant you'll see (eg: Mexican, Italian etc)
$cat_query = array(
'taxonomy' => 'category',
'field' => 'slug',
'terms' => $restaurant_category,
'operator' => 'IN'
);
// Go and get the posts
$args = array(
'post_type' => 'post',
'post_status' => 'publish',
'posts_per_page' => -20,
'geocode' => $user_geocode, // WOuld love this to work!!!
'orderby' => 'geocode', // Would love this to work!!!
'fields' => 'ids',
'tax_query' => array(
'relation' => 'AND',
$cat_query,
)
);
$posts = get_posts($args);
答案 0 :(得分:2)
如果您将后期数据保存在数据库中(将坐标分为纬度和逻辑两个字段),您可以使用余弦定律的大地形式来查找点之间的距离。Reference
COS(d / R)= COS(LAT1)COS(LAT2)COS(long2-long1)+ SIN(LAT1)SIN(LAT2)
其中R =地球半径(6367公里,3959英里)
以下SQL查询将提供以kms为单位的距离,其中$ center_lat& $ center_lng是用户位置。
$postids=$wpdb->get_col( $wpdb->prepare("SELECT name, lat, lng,
( 6367 * acos( cos( radians(%f) ) * cos( radians( lat ) ) * cos( radians( lng ) - radians(%f) ) + sin( radians(%f) ) * sin( radians( lat ) ) ) ) AS distance FROM mytable HAVING distance < %d ORDER BY distance LIMIT 0 , 5",
$center_lat,$center_lng,$center_lat,$radius));
if ( $postids )
{
foreach ( $postids as $id )
{
echo $id->name;
echo $id->distance;
//etc
}
}
答案 1 :(得分:0)
您肯定需要以不同方式存储您的值。当我这样做时,我已经使用了一些类似于
的表格CREATE TABLE `geo_db` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`post_id` int(11) DEFAULT NULL,
`lat` float DEFAULT NULL,
`lng` float DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `post_id` (`post_id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=latin1;
您也可以使用GEOMETRY类型的单列,但这对于比较地理点是很好的。然后在你的插件中,你将修改WP_Query中使用的sql
function geo_posts_fields( $sql, WP_Query $wp_query ){
global $wpdb;
// get your user coords here. explode $user_geocode or store in custom db as well.
$lat = 45;
$lng = -122;
if( $wp_query->query_vars['orderby'] == 'geocode' )
$sql .= $wpdb->prepare( ", ROUND( ( 3959 * acos( cos( radians(geo_db.lat) ) * cos( radians( %f ) )
* cos( radians(%f) - radians(geo_db.lng)) + sin(radians(geo_db.lat))
* sin( radians(%f)))), 1 ) AS `distance` ", $lat, $lng, $lat );
return $sql;
}
function geo_posts_join( $sql, WP_Query $wp_query ){
global $wpdb;
if( $wp_query->query_vars['orderby'] == 'geocode' )
$sql .= " LEFT JOIN geo_db ON $wpdb->posts.ID = geo_db.post_id ";
return $sql;
}
function geo_posts_orderby( $sql, WP_Query $wp_query ){
if( $wp_query->query_vars['orderby'] == 'geocode' )
$sql = " `distance` ASC, ".$sql;
return $sql;
}
function geo_posts_request( $sql, WP_Query $wp_query ){
// just to see whats going on
var_dump( $sql );
return $sql;
}
add_filter( 'posts_fields', 'geo_posts_fields', 10, 2 );
add_filter( 'posts_join', 'geo_posts_join', 10, 2 );
add_filter( 'posts_orderby', 'geo_posts_orderby', 10, 2 );
add_filter( 'posts_request', 'geo_posts_request', 10, 2 );
最后,你需要注册一个查询var才能使用orderby作为get_posts的参数,我建议你创建一个新的WP_Query
$geo_posts = new WP_Query( array(
'post_type' => 'any',
'orderby' => 'geocode'
) );
while( $geo_posts->have_posts() ): $geo_post->the_post(); // etc