Archiv » CakePHP » Umkreissuche - OpenGeoDB und...

Umkreissuche - OpenGeoDB und CakePHP

Benötigt wird ein Controller und Model für die Geokoordinaten (z.B. OpenGeoDB) und ein Model und Controller mit Firmen (Firmenname, PLZ, Land, Längengrad, Breitengrad) Über die GeoDB ließe sich auch anhand der Postleitzahl direkt die Umkreissuche durchführen. Bei diesem Beispiel gehen wir davon aus, dass die OpenGeoDB nicht alle Postleitzahlengebiete beinhaltet und die Firmen die Längen- und Breitengrade mitliefern.
<?php

// input zipcode ##$this->data["Company"]["Companyplz"]##
// find Company with zipcode from posted form
$geo_coordinates = $this->Geolocator->find('first', array('conditions' => array('Geolocator.zipcode LIKE' => trim($this->data["Company"]["Companyplz"]).'%'),
                        'fields' => array('lon','lat','city','state')));

// mysql-Ausgabefelder für Umkreissuche mit Längen- und Breitengrad der Firma
$fields = array('Company.*', 'Geolocation.land',
        'ACOS(SIN(RADIANS(lat)) * SIN(RADIANS('.$geo_coordinates["Geolocation"]["lat"].'))
         + COS(RADIANS(lat)) * COS(RADIANS('
.$geo_coordinates["Geolocation"]["lat"].')) * COS(RADIANS(lon)
         - RADIANS('
.$geo_coordinates["Geolocation"]["lon"].'))
         ) * 6380 AS `distance`'
);

// Bedingungen für die Umkreissuche
$conditions = array('(ACOS(
         SIN(RADIANS(lat)) * SIN(RADIANS('
.$geo_coordinates["Geolocation"]["lat"].'))
         + COS(RADIANS(lat)) * COS(RADIANS('
.$geo_coordinates["Geolocation"]["lat"].')) * COS(RADIANS(lon)
         - RADIANS('
.$geo_coordinates["Geolocation"]["lon"].'))
         ) * 6380 AND Geolocation.zipcode = Company.zipcode) ||
                                  (Company.zipcode='
.trim($this->data["Company"]["Companyplz"]).' AND Geolocation.zipcode='.trim($this->data["Company"]["Companyplz"]).')');

// Sortiere Umkreissuche-Ergebnise aufsteigend nach Distanz (Kilometer)
$orderby = array('distance' => 'ASC');
                               
// mySQL-Query für die gesamte Umkreissuche mit einer max. Distanz von 200km
$CompanyResults = $this->Geolocation->find('all', array('conditions' => $conditions,
        'fields'        => $fields,
        'order' => $orderby,
        'group' => array('distance HAVING distance <200'),
        'limit' => 100));

/*                                                     
Ergebnisse der $CompanyResults (print_r):
Array
(
        [0] => Array
                (
                        [Factory] => Array
                                (
                                        [id] => 7
                                        [company] => Musterfirma
                                        [street] => Musterstraße 3
                                        [zipcode] => 22111
                                        [city] => Hamburg
                                        [longitude] => 9.9623374
                                        [latitude] => 53.5494149
                                )

                        [Geolocator] => Array
                                (
                                        [land] => Deutschland
                                )

                        [0] => Array
                                (
                                        [distance] => 93.0386003085903
                                )

                )
)
*/

                                                       
?>