it-swarm.com.de

Finden aller Ergebnisse aus der Datenbank innerhalb von 500 Meilen des angegebenen Breiten- und Längengrads

Ich stecke in diesem Problem, bei dem die Hauptanforderung darin besteht, alle Ergebnisse aus der Datenbank zu finden, die sich innerhalb von 500 Meilen von dem angegebenen Breiten- und Längengrad befinden. Ich habe die lati und longi zusammen mit der Postleitzahl dieses Breiten- und Längengrads in der post_meta gespeichert. Nun besteht die Idee darin, dass der Benutzer nach jeder Postleitzahl sucht und die Meilen aus der Dropdown-Liste auswählt, für die alle Ergebnisse passend sind, für die die Abfrage kommen soll Beispiel.

Der Benutzer führt eine solche Abfrage durch

500 mi von 51310

Die Abfrage sollte alle Ergebnisse zurückgeben, die sich innerhalb von 500 Meilen von der Postleitzahl 51310 befinden.

Folgendes habe ich bisher getan. Dies ist die Hauptfunktion, mit der die Abfrage tatsächlich an die Datenbank gesendet wird.

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

Und um den Geocode zu finden, habe ich diese Funktion geschrieben.

$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;
    }

Wenn ich das Feld "Innerhalb" nicht auswähle, gibt dieser Code die genauen Ergebnisse der jeweiligen Postleitzahl zurück. Wenn ich jedoch "Innerhalb" auswähle, wird nichts angezeigt. Kann mir jemand sagen, was ich in diesem Code falsch mache.

2
Mohsin

Das Problem bestand darin, dass beim Senden der Abfrage an die Datenbank die Array-Ebene geändert wurde, außer dass der Wert 's' nicht leer wurde, wodurch das Abrufen meiner Datensätze verhindert wurde, und der dritte und wichtigste war der Weg Ich habe meine Frage gestellt, indem ich meine Funktion geändert habe, um das Problem zu beheben.

Hier ist der aktualisierte Code für diese Logik für den Fall, dass jemand anderes eine solche Funktion ausführen muss.

Die Hauptfunktion, bei der alle Daten gesammelt und eine Abfrage durchgeführt werden

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-Abfrage-Funktion, die tatsächlich die Magie tat

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

Und jetzt die letzte Funktion, die das Lat und Long von der Postleitzahl, die der Benutzer eingibt, abrief

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;
    }
}

Um einen Beitrag zu finden, der auf dieser Antwort basiert, muss die Postleitzahl in der Tabelle post_meta gespeichert sein, damit Lati und Longi abgerufen werden können. Die im Code angegebene Formel zum Auffinden der maximalen und minimalen Grenzen gibt Lat und Longi an. Ich hoffe, ich habe die Antwort ausführlich gegeben, wenn nicht, können Sie gerne Kommentare schreiben.

0
Mohsin