我有一个工作laravel选择查询。我该如何添加过滤器?

时间:2017-07-13 14:07:16

标签: php mysql laravel geolocation xampp

嘿,大家好吗?提前谢谢。
我在laravel模型中编写了一个工作函数,它执行geosearch并按距离返回搜索顺序。它工作得很漂亮。

 public static function searchByDistance($distance, $unit)
{
    //spatial queries
   // $circle_radius = 6371; 
    $circle_radius = 3959; 
    $max_distance = $distance;
    $lat = Auth::user()->getLoc()->latitude;
    $lng = Auth::user()->getLoc()->longitude;
    //get all nearby places
     $nearbyusers = DB::select(
           'SELECT * FROM
                (SELECT users.id, users.country, places.name, places.state_code, places.latitude, places.longitude, (' . $circle_radius . ' * acos(cos(radians(' . $lat . ')) * cos(radians(latitude)) *
                cos(radians(longitude) - radians(' . $lng . ')) +
                sin(radians(' . $lat . ')) * sin(radians(latitude))))
                AS distance
                FROM users
                LEFT JOIN places ON users.suburb=places.name) AS distances
            WHERE distance < ' . $max_distance . '
            ORDER BY distance;
     ');        
   $nearbyusers = (object)$nearbyusers;
    return $nearbyusers;
}
然而,我有一个问题。我想调用该函数,返回一个查询并继续对其进行add ->where()操作,直到我准备好使用get()并返回结果。

我无法使用where() or get()而且我知道原因。它的格式不正确。 有没有人可以帮我修改/改变功能,这样我可以在返回$nearbyusers值后添加更多过滤器?

欢呼声

4 个答案:

答案 0 :(得分:1)

查看official documentation for raw expressions我认为您正在寻找的内容。无论如何,你必须将原始查询更改为&#34; builded&#34;查询如下:

$nearbyusersquery = DB::table('users')
    ->select(DB::RAW('SELECT users.id, users.country, places.name, places.state_code, places.latitude, places.longitude, (' . $circle_radius . ' * acos(cos(radians(' . $lat . ')) * cos(radians(latitude)) *
            cos(radians(longitude) - radians(' . $lng . ')) +
            sin(radians(' . $lat . ')) * sin(radians(latitude))))
            AS distance'))
    ->leftJoin('places', 'users.suburb', '=', 'places.name')
    ->where('distance', '<', $max_distance)
    ->orderBy('distance');      

return $nearbyusersquery

通过这种方式,您的方法将返回一个Builder对象,该对象可以与其他语句链接。

答案 1 :(得分:1)

您将要查看底层的Fluent查询构建器系统。就目前而言,您的查询是独立的。这个特定的人也可能需要保持独立。

为了以您希望的方式连接到Fluent,您需要传入查询(这应该自动解析),添加到它,然后返回查询。与您当前的功能相关,这可能需要一种与您拥有的方法完全不同的方法(尽管您拥有的是您希望最终得到的查询的良好模型)。

查看the docs about query scopes,这可能正在解决您尝试集成它的方式。另外,请查看代码本身such as this one for the JoinClause function,以了解如何构建代码。

您需要获取并返回查询对象的基本元素。这意味着它不能是静态方法(它需要对象实例),并且根据您采用的方法,您将返回传入的$query对象(范围)或{{1 (它们的实例是模型对象,本身)。

您需要找到一种方法将您所拥有的查询封装到您需要的细分中。它可能类似于:

$this

注意查询构建部分中没有实际的public function byDistance($distance, $unit) { $lat = Auth::user()->getLoc()->latitude; $lng = Auth::user()->getLoc()->longitude; return $this->join(DB::select('SELECT users.id, users.country, places.name, places.state_code, places.latitude, places.longitude, (' . $circle_radius . ' * acos(cos(radians(' . $lat . ')) * cos(radians(latitude)) * cos(radians(longitude) - radians(' . $lng . ')) + sin(radians(' . $lat . ')) * sin(radians(latitude))) AS distance'), 'users.id', 'distance.user_id = users.id') ->leftJoin('places', 'users.suburb = places.name') ->where('distance', '<', $distance) ->orderBy('distance'); } (尽管嵌套选择),并且缺少任何类型的实际提取。这样做是添加到当前查询,然后在最终调用select或其他获取函数时构建。这为您提供了一个较大查询的离散段,您可以在调用它时添加它。

答案 2 :(得分:0)

你也可以用sql来做。例如:

   $filtr = "";
$filtr2 = "";

If (something)
 $filtr =" and field = var";

If (somethingelse)
   $filtr2 = " and field2 = other_var";

// this can be in the elloquent query
$query = "select .... 
from .... 
Where 1=1 
     $filtr
     $filtr2
";

修改

//assuming the country Id is passed to your controller
// first initialize the filter as empty string
$countryFilter = "";

// if the country is not null or empty replace the filter
if ($country != null && $country != "")  
    $countryFilter = "and country = $countryFilter";

$nearbyusers = DB::select(
           'SELECT * FROM
                (SELECT users.id, users.country, places.name, places.state_code, places.latitude, places.longitude, (' . $circle_radius . ' * acos(cos(radians(' . $lat . ')) * cos(radians(latitude)) *
                cos(radians(longitude) - radians(' . $lng . ')) +
                sin(radians(' . $lat . ')) * sin(radians(latitude))))
                AS distance
                FROM users
                LEFT JOIN places ON users.suburb=places.name) AS distances
            WHERE distance < ' . $max_distance . '
            -- if no country was selected then it will just be an empty line
            $countryFilter
            ORDER BY distance;
     ');  

答案 3 :(得分:0)

好像往常一样,自己解决了。问题很简单。您所要做的就是查找与结果匹配的用户对象并将它们推入数组中。然后返回该数组,你可以使用这些功能!因此,如果您想从原始查询中获取可通过的对象,那么您就是这么做的。再次感谢您的有用答案。问题真的很简单。最后,我摆弄它而不是从互联网上获得任何答案。

//spatial queries        

                    $circle_radius = 6371;       

                   // $circle_radius = 3959; 


                $max_distance = request('distance');
                $lat = Auth::user()->getLoc()->latitude;
                $lng = Auth::user()->getLoc()->longitude;

                //get all nearby places
                 $nearbyusers = DB::select(
                       'SELECT * FROM
                            (SELECT users.id, users.country, places.name, places.state_code, places.latitude, places.longitude, (' . $circle_radius . ' * acos(cos(radians(' . $lat . ')) * cos(radians(latitude)) *
                            cos(radians(longitude) - radians(' . $lng . ')) +
                            sin(radians(' . $lat . ')) * sin(radians(latitude))))
                            AS distance
                            FROM users
                            LEFT JOIN places ON users.suburb=places.name) AS distances
                        WHERE distance < ' . $max_distance . '
                        ORDER BY distance;
                 ');      

                 $users = [];

                 foreach($nearbyusers as $user)
                 {
                    array_push($users, User::where('id', $user->id)->first());
                 }



               //$nearbyusers = (object)$nearbyusers;


                return Response::json( array( 
                'searchsuccess' => (String) view('members.yessearch', compact('users')) 
                ) );