Reputation: 59
In cakephp 2, I was able to use a virtualField for this, but seems impossible in 3. I have been struggling with this for two days without luck from the internet or the cakephp manual. I get no errors, but I do get a blank return.
My code in my controller looks like this:
if (isset($this->request->data['location']) && (isset($this->request->data['radius']))){
$radius = $this->request->data['radius'];
$location = $this->request->data['location'];
$address = $location; // Google HQ
$HttpSocket = new Client();
$geocode = $HttpSocket->get('http://maps.google.com/maps/api/geocode/json?address='.$address.'&sensor=false');
$geocode = $geocode->json;
if ($geocode['status'] == "OK"){
$lat = $geocode['results'][0]['geometry']['location']['lat'];
$lon = $geocode['results'][0]['geometry']['location']['lng'];
$R = 6371; // earth's mean radius, km
// first-cut bounding box (in degrees)
$maxLat = $lat + rad2deg($radius/$R);
$minLat = $lat - rad2deg($radius/$R);
// compensate for degrees longitude getting smaller with increasing latitude
$maxLon = $lon + rad2deg($radius/$R/cos(deg2rad($lat)));
$minLon = $lon - rad2deg($radius/$R/cos(deg2rad($lat)));
$conditions[] = ['Venues.lat' => "'BETWEEN '".$minLat."' AND '".$maxLat."'"];
$conditions[] = ['Venues.lon' => "'BETWEEN :'".$minLon."' AND :'".$maxLon."'"];
}
$this->paginate =[
'limit' => 10,
'order' => ['Quads.date' => 'asc'],
'conditions' => $conditions,
'contain' => [
'Performers' => ['Genres'],
'Users' => ['Profiles'],
'Venues' => ['fields' => [
'name',
'id',
'verified',
'address1',
'city',
'zip_code'], 'States'=>['Countries']],
'Categories',
'Likes' => ['Users' => ['Profiles']]]];
$quads = $this->paginate();
Upvotes: 0
Views: 116
Reputation: 60493
Impossible is (nearly) nothing. The old virtual fields concept is gone, right, the new ORM is flexible enough so that this isn't necessary anymore.
Your problem is that you are defining the conditions the wrong way, what you are doing there by specifying key => value
sets, is creating ordinary operator conditions, where the value is going to be escaped/casted according to the column type. In case you really don't receive any errors, I'd assume that the lat/lan
columns are of a numeric type, so your BETWEEN ...
strings do end up as numbers, and the conditions will look something like
Venus.lat = 0 AND Venus.lon = 0
Also note that you are creating a nested array, ie
[
['keyA' => 'value'],
['keyB' => 'value']
]
and while this works, you may run into further problems in case you're not aware of it, so you'd better stick with
[
'keyA' => 'value',
'keyB' => 'value'
]
unless there's actually a technical reason to use nested conditions.
That being said, you can use expressions to build the proper conditions, like
$conditions[] = $this->Quads->Venues
->query()->newExpr()->between('Venues.lat', $minLat, $maxLat);
$conditions[] = $this->Quads->Venues
->query()->newExpr()->between('Venues.lon', $minLon, $maxLon);
This will safely create proper conditions like
Venus.lat BETWEEN a AND b AND Venus.lon BETWEEN x AND Y
Note that it is advised to create the expressions via the table that holds the columns (VenuesTable
in this case), as you'd otherwise have to manually specify the column type (see the fourth argument of QueryExpression::between()
) in order for the correct casting/escaping to be applied!
See also
Upvotes: 1