2

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);
4

2 に答える 2

2

投稿データをデータベースに保存すると (座標を緯度と経度の 2 つのフィールドに分割します)、コサインの法則の測地形式を使用して、ポイント間の距離を見つけることができます。参照

cos(d/R)=cos(lat1)cos(lat2)cos(long2-long1)+sin(lat1)sin(lat2)

ここで、R = 地球の半径 (6367 キロ、3959 マイル)

次の SQL クエリは、距離をキロ単位で提供します。ここで、$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
    }   
}   

クエリは、ここで使用したコードに基づいていますが、ここにある情報で変更されています。確認する WordPress へのアクセス権がありません。

于 2013-11-04T01:09:50.540 に答える
1

値を別の方法で保存する必要があることは間違いありません。これを行ったとき、次のようなテーブルを使用しました

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 タイプの 1 つの列を使用することもできますが、ジオ ポイントを比較するにはこれで問題ありません。次に、プラグインで、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 );

最後に、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
于 2013-11-05T18:44:12.947 に答える