私はこの問題に立ち往生しています。ここでの主な要件は、与えられた緯度と経度から500マイル以内にあるすべての結果をデータベースから見つけることです。 latiとlongiをそれらの緯度と経度の郵便番号と一緒にpost_metaに保存しました。これで、ユーザーが郵便番号を検索してドロップダウンからマイルを選択し、そのクエリに一致するすべての結果が得られるようになります。インスタンス。
ユーザーはこのような質問をします
51310から500マイル
クエリは、郵便番号51310の500マイル以内にあるすべての結果を返すはずです。
これが私がこれまでにやったことです。これが実際にデータベースへの問い合わせをしている主な機能です。
if (isset($_GET['s']) && !empty($_GET['s'])) {
$searchterm = isset($q->query_vars['s']) ? sanitize_text_field($q->query_vars['s']) : '';
// we have to remove the "s" parameter from the query, because it will prevent the posts from being found
$q->query_vars['s'] = '';
if ($searchterm != '') {
$search_radius = $this->geocode($searchterm);
if (!$search_radius) {
return false;
}
$lat = $search_radius['lat']; // get the lat of the requested address
$lng = $search_radius['lng']; // get the lng of the requested address
// we'll want everything within, say, 30km distance
$distance = isset($_GET['within']) && !empty($_GET['within']) ? floatval($_GET['within']) : 50;
// earth's radius in km = ~6371
$radius = auto_listings_metric() == 'yes' ? 6371 : 3950;
// latitude boundaries
$maxlat = $lat + rad2deg($distance / $radius);
$minlat = $lat - rad2deg($distance / $radius);
// longitude boundaries (longitude gets smaller when latitude increases)
$maxlng = $lng + rad2deg($distance / $radius / cos(deg2rad($lat)));
$minlng = $lng - rad2deg($distance / $radius / cos(deg2rad($lat)));
// build the meta query array
$radius_array = array(
'relation' => 'AND',
);
$radius_array[] = array(
'key' => '_al_listing_lat',
'value' => array($minlat, $maxlat),
'type' => 'DECIMAL(10,5)',
'compare' => 'BETWEEN',
);
$radius_array[] = array(
'key' => '_al_listing_lng',
'value' => array($minlng, $maxlng),
'type' => 'DECIMAL(10,5)',
'compare' => 'BETWEEN',
);
return apply_filters('auto_listings_search_radius_args', $radius_array);
そして、私がこの関数を書いたジオコードを見つけるために。
$address = urlencode(esc_html($address));
// google map geocode api url
$url = auto_listings_google_geocode_maps_url($address);
$arrContextOptions = array(
"ssl" => array(
"verify_peer" => false,
"verify_peer_name" => false,
),
);
// get the json response
$resp_json = file_get_contents($url, false, stream_context_create($arrContextOptions));
// decode the json
$resp = json_decode($resp_json, true);
//pp( $resp );
// response status will be 'OK', if able to geocode given address
if ($resp['status'] == 'OK') {
// get the lat and lng
$lat = $resp['results'][0]['geometry']['location']['lat'];
$lng = $resp['results'][0]['geometry']['location']['lng'];
// verify if data is complete
if ($lat && $lng) {
return array(
'lat' => $lat,
'lng' => $lng,
);
} else {
return false;
}
} else {
return false;
}
フィールド内を選択しない場合、このコードは特定の郵便番号の正確な結果を返しますが、フィールド内を選択した場合は何も表示されません。このコードの中で私が間違っていることを誰かに教えてもらえますか。
問題は、クエリをデータベースに送信したときに、配列のレベルが変更されていて、レコードの取得が妨げられていたために 's'の値が空にならなかったことです。機能を変更してクエリを実行したところ、問題は解決しました。
他の誰かがそのような機能を作る必要がある場合のために、これはこの論理のために更新されたコードです。
すべてのデータが集まってクエリを作成する主な機能
public function pre_get_posts($q) {
// check if the user is requesting an admin page
if (is_admin() || !$q->is_main_query())
return;
if (!is_post_type_archive('auto-listing'))
return;
if (!is_search())
return;
$meta_query = array();
$year_query[] = $this->year_query();
$model_query[] = $this->model_query();
$condition_query[] = $this->condition_query();
$odometer_query[] = $this->odometer_query();
$price_query[] = $this->price_meta_query();
$body_type_query = $this->body_type_query();
$country_query = $this->country_query();
$transmission_query = $this->transmission_query();
$radius_query[] = $this->radius_query($q);
$query_1 = array_merge($country_query, $year_query, $model_query, $condition_query, $price_query, $odometer_query, $transmission_query);
// if our radius query fails, fall back to keyword searching
// will fail with no map API key
if (empty($radius_query[0]) || !$radius_query[0]) {
$keyword_query[] = $this->keyword_query($q);
$query_2 = $keyword_query;
} else {
$query_2 = $radius_query;
}
// if no keyword
if (empty($_GET['s'])) {
$query_1['relation'] = 'AND';
$meta_query[] = $query_1;
}
// if keyword
if (!empty($_GET['s'])) {
$query_2['relation'] = 'OR';
$meta_query[] = $query_1;
$meta_query[] = $query_2;
$meta_query['relation'] = 'AND';
}
$q->set('meta_query', $meta_query);
$q->set('tax_query', $body_type_query);
$q->set('post_type', 'auto-listing');
}
実際に魔法をやっていたRadiusクエリ関数
public function radius_query($q) {
if (isset($_GET['s']) && !empty($_GET['s'])) {
$searchterm = isset($q->query_vars['s']) ? sanitize_text_field($q->query_vars['s']) : '';
// we have to remove the "s" parameter from the query, because it will prevent the posts from being found
$q->query_vars['s'] = '';
if ($searchterm != '') {
$search_radius = $this->geocode($searchterm);
if (!$search_radius)
return false;
$lat = $search_radius['lat']; // get the lat of the requested address
$lng = $search_radius['lng']; // get the lng of the requested address
// we'll want everything within, say, 30km distance
$distance = isset($_GET['within']) && !empty($_GET['within']) ? floatval($_GET['within']) : 0.1;
// earth's radius in km = ~6371
$radius = auto_listings_metric() == 'yes' ? 6371 : 3950;
// latitude boundaries
$maxlat = $lat + rad2deg($distance / $radius);
$minlat = $lat - rad2deg($distance / $radius);
// longitude boundaries (longitude gets smaller when latitude increases)
$maxlng = $lng + rad2deg($distance / $radius / cos(deg2rad($lat)));
$minlng = $lng - rad2deg($distance / $radius / cos(deg2rad($lat)));
// build the meta query array
$radius_array = array(
'relation' => 'AND',
);
$radius_array[] = array(
'key' => '_al_listing_lat',
'value' => array($minlat, $maxlat),
'type' => 'DECIMAL(10,5)',
'compare' => 'BETWEEN',
);
$radius_array[] = array(
'key' => '_al_listing_lng',
'value' => array($minlng, $maxlng),
'type' => 'DECIMAL(10,5)',
'compare' => 'BETWEEN',
);
return apply_filters('auto_listings_search_radius_args', $radius_array);
}
}
}
ユーザーが入力したZipコードから緯度と経度を取得していた最後の関数 /
private function geocode($address) {
// url encode the address
$address = urlencode(esc_html($address));
// google map geocode api url
$url = auto_listings_google_geocode_maps_url($address);
$arrContextOptions = array(
"ssl" => array(
"verify_peer" => false,
"verify_peer_name" => false,
),
);
// get the json response
$resp_json = file_get_contents($url, false, stream_context_create($arrContextOptions));
// decode the json
$resp = json_decode($resp_json, true);
//pp( $resp );
// response status will be 'OK', if able to geocode given address
if ($resp['status'] == 'OK') {
// get the lat and lng
$lat = $resp['results'][0]['geometry']['location']['lat'];
$lng = $resp['results'][0]['geometry']['location']['lng'];
// verify if data is complete
if ($lat && $lng) {
return array(
'lat' => $lat,
'lng' => $lng,
);
} else {
return false;
}
} else {
return false;
}
}
この答えに基づいて投稿を見つけるには、郵便番号をpost_metaテーブルに格納してlatiとlongiを取得し、コードで指定された式でmaxとminの境界を検索することでlatとlngを取得する必要があります。そうでない場合は、詳細に回答してください。