. */ /** * Easily add longitude and latitude columns to your records and use inherited functionality for * calculating distances * * @package Doctrine * @subpackage Template * @license http://www.opensource.org/licenses/lgpl-license.php LGPL * @link www.phpdoctrine.org * @since 1.0 * @version $Revision$ * @author Konsta Vesterinen * @author Jonathan H. Wage */ class Doctrine_Template_Geographical extends Doctrine_Template { /** * Array of geographical options * * @var string */ protected $_options = array('latitude' => array('name' => 'latitude', 'type' => 'float', 'size' => null, 'options' => array()), 'longitude' => array('name' => 'longitude', 'type' => 'float', 'size' => null, 'options' => array())); /** * Set table definition for Geographical behavior * * @return void */ public function setTableDefinition() { $this->hasColumn($this->_options['latitude']['name'], $this->_options['latitude']['type'], $this->_options['latitude']['size'], $this->_options['latitude']['options']); $this->hasColumn($this->_options['longitude']['name'], $this->_options['longitude']['type'], $this->_options['longitude']['size'], $this->_options['longitude']['options']); } /** * Initiate and get a distance query with the select parts for the number of kilometers and miles * between this record and other zipcode records in the database * * @return Doctrine_Query $query */ public function getDistanceQuery() { $invoker = $this->getInvoker(); $query = $invoker->getTable()->createQuery(); $rootAlias = $query->getRootAlias(); $latName = $this->_options['latitude']['name']; $longName = $this->_options['longitude']['name']; $query->addSelect($rootAlias . '.*'); $sql = "((ACOS(SIN(%s * PI() / 180) * SIN(" . $rootAlias . "." . $latName . " * PI() / 180) + COS(%s * PI() / 180) * COS(" . $rootAlias . "." . $latName . " * PI() / 180) * COS((%s - " . $rootAlias . "." . $longName . ") * PI() / 180)) * 180 / PI()) * 60 * %s) as %s"; $milesSql = sprintf($sql, $invoker->get('latitude'), $invoker->get('latitude'), $invoker->get('longitude'), '1.1515', 'miles'); $query->addSelect($milesSql); $kilometersSql = sprintf($sql, $invoker->get('latitude'), $invoker->get('latitude'), $invoker->get('longitude'), '1.1515 * 1.609344', 'kilometers'); $query->addSelect($kilometersSql); return $query; } /** * Get distance between this record and another * * @param string $Doctrine_Record * @param string $kilometers * @return integer */ public function getDistance(Doctrine_Record $record, $kilometers = false) { $query = $this->getDistanceQuery($kilometers); $conditions = array(); $values = array(); foreach ((array) $record->getTable()->getIdentifier() as $id) { $conditions[] = $query->getRootAlias() . '.' . $id . ' = ?'; $values[] = $record->get($id); } $where = implode(' AND ', $conditions); $query->addWhere($where, $values); $query->limit(1); $result = $query->execute()->getFirst(); if (isset($result['kilometers']) && $result['miles']) { return $kilometers ? $result->get('kilometers'):$result->get('miles'); } else { return 0; } } }