Skip to content

Instantly share code, notes, and snippets.

@thodeveloper
Forked from ReedD/AppModel.php
Created February 18, 2016 07:32
Show Gist options
  • Save thodeveloper/99cedcf5360aedca8858 to your computer and use it in GitHub Desktop.
Save thodeveloper/99cedcf5360aedca8858 to your computer and use it in GitHub Desktop.

Revisions

  1. @ReedD ReedD revised this gist Jan 22, 2014. 1 changed file with 3 additions and 3 deletions.
    6 changes: 3 additions & 3 deletions AppModel.php
    Original file line number Diff line number Diff line change
    @@ -33,10 +33,10 @@ class AppModel extends Model {
    */
    public function distanceQuery($opts = array()) {
    $defaults = array(
    'latitude' => 0,
    'latitude' => 0,
    'longitude' => 0,
    'alias' => $this->alias,
    'radius' => false
    'alias' => $this->alias,
    'radius' => false
    );
    $opts = Set::merge($defaults, $opts);

  2. @ReedD ReedD revised this gist Jan 22, 2014. 1 changed file with 1 addition and 0 deletions.
    1 change: 1 addition & 0 deletions AppModel.php
    Original file line number Diff line number Diff line change
    @@ -1,6 +1,7 @@
    <?php

    App::uses('Model', 'Model');
    App::uses('String', 'Utility');

    class AppModel extends Model {

  3. @ReedD ReedD revised this gist Jan 22, 2014. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion AppModel.php
    Original file line number Diff line number Diff line change
    @@ -32,7 +32,7 @@ class AppModel extends Model {
    */
    public function distanceQuery($opts = array()) {
    $defaults = array(
    'latitude' => 0,
    'latitude' => 0,
    'longitude' => 0,
    'alias' => $this->alias,
    'radius' => false
  4. @ReedD ReedD created this gist Jan 22, 2014.
    74 changes: 74 additions & 0 deletions AppModel.php
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,74 @@
    <?php

    App::uses('Model', 'Model');

    class AppModel extends Model {

    /**
    * @author Reed Dadoune
    * distanceQuery
    * A genral case distance query builder
    * Pass a number of options to this function and recieve a query
    * you can pass to either the find or paginate functions to get
    * objects back by distance
    *
    * Example:
    * $query = $this->Model->distanceQuery(array(
    * 'latitude' => 34.2746405,
    * 'longitude' => -119.2290053
    * ));
    * $query['conditions']['published'] = true;
    * $results = $this->Model->find('all', $query);
    *
    * @param array $opts Options
    * - latitude The latitude coordinate of the center point
    * - longitude The longitude coordinate of the center point
    * - alias The model name of the query this is for
    * defaults to the current model alias
    * - radius The distance to at which to find objects at
    * defaults to false in which case distance is calculated
    * only for the sort order
    * @return array A query that can be modified and passed to find or paginate
    */
    public function distanceQuery($opts = array()) {
    $defaults = array(
    'latitude' => 0,
    'longitude' => 0,
    'alias' => $this->alias,
    'radius' => false
    );
    $opts = Set::merge($defaults, $opts);

    $query = array(
    'fields' => array(
    '*',
    String::insert(
    '3956 * 2 *
    ASIN(SQRT(
    POWER(SIN((:latitude - ABS(:alias.latitude)) * PI() / 180 / 2), 2) +
    COS(:latitude * PI() / 180) *
    COS(ABS(:alias.latitude) * PI() / 180) *
    POWER(SIN((:longitude - :alias.longitude) * PI() / 180 / 2), 2)
    )) AS distance',
    array('alias' => $opts['alias'], 'latitude' => $opts['latitude'], 'longitude' => $opts['longitude'])
    )
    ),
    'order' => array('distance' => 'ASC')
    );

    if ($opts['radius']) {
    $longitudeLower = $opts['longitude'] - $opts['radius'] / abs(cos(deg2rad($opts['latitude'])) * 69);
    $longitudeUpper = $opts['longitude'] + $opts['radius'] / abs(cos(deg2rad($opts['latitude'])) * 69);
    $latitudeLower = $opts['latitude'] - ($opts['radius'] / 69);
    $latitudeUpper = $opts['latitude'] + ($opts['radius'] / 69);
    $query['conditions'] = array(
    String::insert(':alias.latitude BETWEEN ? AND ?', array('alias' => $opts['alias'])) => array($latitudeLower, $latitudeUpper),
    String::insert(':alias.longitude BETWEEN ? AND ?', array('alias' => $opts['alias'])) => array($longitudeLower, $longitudeUpper)
    );
    $query['group'] = sprintf('%s.id HAVING distance < %f', $opts['alias'], $opts['radius']);
    }

    return $query;
    }
    }