1

I have a table called owners that is a list of store owners, and I would like to query this table with its relation stores and get the distance the store is from the user. For now the user location is hard coded, but I plan to pass that in to the Query Scope if I can get it working. Any tips are much appreciated, thank you!

<?php class Owner extends Eloquent {

protected $table = 'owners';    

public function scopeDistance($query) {

    $lat = '45.529999';
    $lng = '-122.680000';

    return $query->select(DB::raw("*,
                          ( 3959 * acos( cos( radians(?) ) *
                            cos( radians( lat ) )
                            * cos( radians( lng ) - radians(?)
                            ) + sin( radians(?) ) *
                            sin( radians( lat ) ) )
                          ) AS distance"))
            ->setBindings([$lat, $lng, $lat]);

}

public function stores()
{
    return $this->belongsTo('Store','store_id')->Distance();
}

public function storesDist()
{
    $lat = '47';
    $lng = '-124';
    return $this->belongsTo('Store','store_id')->select(DB::raw("*,
                          ( 3959 * acos( cos( radians(?) ) *
                            cos( radians( lat ) )
                            * cos( radians( lng ) - radians(?)
                             ) + sin( radians(?) ) *
                             sin( radians( lat ) ) )
                           ) AS distance"))
             ->setBindings([$lat, $lng, $lat]);
}

<?php

class OwnersController extends \BaseController {


public function getStoresNearUserA()
{

 // This returns  Call to undefined method Illuminate\Database\Query\Builder::Distance()
 return Owner::orderBy('id')->with('stores')->get();

 }

public function getStoresNearUserB()
{

 // This works
 return Owner::orderBy('id')->with('storesDist')->get();

}

***********************************************UPDATED

RE: First solution

// app/models/BaseModel.php
<?php

class BaseModel extends Eloquent {


public function scopeDistance($query) {

    return $query->orderBy('id');

}


....app/models/Store.Php
<?php 


class Store extends \Eloquent {

    protected $table = 'owners';


....app/models/Owner.Php
<?php 


class Owner extends \BaseModel {

    protected $table = 'owners';

    public function stores()
    {
        return $this->belongsTo('Store','store_id')->Distance();
    }


...app/controllers/OwnerController.php  
<?php

class OwnersController extends \BaseController {



public function getStoreOwners()
{

        return Owner::orderBy('id')->with('stores')->get();
  }

...My Error :
Call to undefined method Illuminate\Database\Query\Builder::Distance()

1 Answer 1

1

You have error in setBindings - where is the default. So just use 2nd param set to select and you'll be good:

public function scopeDistance($query, $lat, $lng) 
{    
    return $query->select(DB::raw("*,
                          ( 3959 * acos( cos( radians(?) ) *
                            cos( radians( lat ) )
                            * cos( radians( lng ) - radians(?)
                            ) + sin( radians(?) ) *
                            sin( radians( lat ) ) )
                          ) AS distance"))
            ->setBindings([$lat, $lng, $lat], 'select');
}

You could alternatively use

->addBinging($lat, 'select')->addBinding($lng, 'select')->addBinding($lat, 'select');

which would be secure, because now, in case there are any other bindings for select (pretty rare, I admit, but still..) you would mess up the query.

Also mind that you can't use Owner model scope on the relation query like this. I suggest you define this scope in your BaseModel, then Owner and Store models will extend it and you will be able to use the scope in both.

Sign up to request clarification or add additional context in comments.

1 Comment

Looks good thank you very much! I will confirm later this evening when I get home.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.