0
votes

Two tables, with the relationship set up properly in Cakephp:

Property (..., postcode_id,...) and Postcode (id, postcode, latitude, longitude).

A Virtual Field created in Property beforeFind() calculates the distance between a search postcode and the record postcode. Therefore, to get the lat/long, I need to retrieve a record from the Postcode table by the foreign key in the Property record, all within the virtual field declaration.

How can I do this? Multiple SELECTs nested within? Nested find(), which would probably be worse? I thought just using RelatedModel.fieldName would work - it doesn't.

EDIT: Property belongsTo Postcode, Postcode hasMany Property

(Using cakephp v2.4.4)

The Virtual Field in Property beforeFind():

$this->virtualFields['distance'] = 6371 . ' * ACOS(
    (SIN(RADIANS(Postcode.latitude)) * ' . $searchPostcode['latitudeSin'] . ') +
    (COS(RADIANS(Postcode.latitude)) * ' . $searchPostcode['latitudeCos'] . ') *
     COS(RADIANS(Postcode.longitude) - ' . $searchPostcode['longitude'] . ')
)';
2
This does not answer your question directly, but did you look into the bakery at this behavior that you may be able to leverage for solving distances with zip codes - AgRizzo
Thanks, but I'm not sure how much work would be needed for CakePHP 2 compatibility. Either way, I'm hoping there's something more general that I can use here for any calculated field with this issue, not just geographic ones. - StringsOnFire

2 Answers

0
votes

You'll need to do a manual join between the table you're searching and the one that holds the lng/lat, for example, $options['joins'] = array(array('table' => 'model2', 'alias' => 'Model2', 'conditions' => array('Model2.model1_id = Model1.id'))); and then in your virtual field, I think you should be able to use Model2.lat and Model2.lng and have it work.

0
votes

I have it working, but I had to nest another SELECT in each foreign call, which can't be the best solution. For example,

RADIANS((SELECT latitude FROM postcodes WHERE id = Property.postcode_id))

This also means that the same value, latitude, is being retrieved twice, so that's not great.

Please share a better solution if you have one!