创建具有由模型属性和相关透视计数组成的按字段组成的排序依据的搜索表单


Creating a search form with order by fields composed of model properties and related pivot count

我正在尝试为我的Laravel应用程序创建一个搜索表单。 基本上,用户可以输入一些字段(与可搜索的模型相关,如标题)并以不同的方式对其进行排序; 标题,创建日期,还有投票计数或收藏计数。最后两个是数据透视表的结果(多对多关系)。

我一直在为此苦苦挣扎,但我不知道如何进行。这是我到目前为止所拥有的:

public function search(SearchRequest $request)
{
    $posts = Post::where('published', 1);
    if (strlen($request->title) > 0) {
        $posts->where('title', 'like', '%' . $request->title . '%');
    }
    switch($request->order_by) {
        case 'title' : $orderBy = 'title'; break;
        case 'createDate' : $orderBy = 'created_at'; break;
        case 'favorites' : $orderBy = 'post_favorites.count(*)'; break;
        case 'votes' : $orderBy = 'post_votes.count(*)'; break;
    }
    $posts->orderBy($orderBy, $request->order_by_direction);
    $posts = $posts->get();
    var_dump($posts);
}

为了简单起见,我将代码重写为一个典型的博客文章示例。感谢您的建议。

会试一

试,但它没有经过测试,因为没有什么可以测试的等等,所以请耐心等待,其他人可能会让它更简单,但希望它有所帮助。

public function search(SearchRequest $request)
{
    if(count($request->get('title')) > 0){
        $search_text = $request->get('title');
        $order_by = $request->get('order_by');
        $display_by = $request->get('order_by_direction');
        $search_results = Post::where('title', 'like', '%' . $search_text . '%')->get();
        if($display_by == 'asc') return this::orderSearchResults($search_results, $order_by);
        return this::orderSearchResults($search_results, $order_by)->reverse();
    } else {
        //do something else here
    }
}
private function orderSearchResults($search_results, $order_by)
{
        switch ($order_by) {
            case 'title' :
                return $search_results->sortby('title');
                break;
            case 'createDate' :
                return $search_results->sortby('created_at');
                break;
            case 'favorites' :
                return $search_results->sortby(function($search){
                    return count($search['post_favorites']);
                });
                break;
            case 'votes' :
                return $search_results->sortby(function($search){
                    return count($search['post_votes']);
                });
                break;
            default :
                return $search_results;
                break;
        }
}

第二部分基于结果作为集合等返回。

我遇到过类似的情况,我必须让用户在不同的字段上提供搜索选项(搜索姓名、电子邮件、电话......等)并按帖子数量或姓名或电子邮件排序......这按预期工作。我尝试重写代码以匹配您提供的示例。

 // if the user didn't fill the field, we assign default values
  $searchText = $request->input('searchText') ?: null; // the terms we are looking for
  $targetField = $request->input('targetField') ?: 'title'; // in which field we want to search
  $orderBy = $request->input('orderBy') ?: 'id'; // field used to order the results
  $order = $request->input('order') ?: 'DESC'; // order direction
  // from here we start assembling our query depending on the request
  $query = DB::table('posts')->select('*')->where('published', 1);
  // if the user typed something in search bar, we look for those terms
  $query->when($searchText, function($query) use ($searchText,$targetField) {
    return $query->where($targetField,'like','%'.$searchText.'%');
  });
  // if the user wants to order by votes
  $query->when($orderBy === 'votes', function ($query) use ($order) {
    return $query->addSelect(DB::raw('(select count(post_id) from post_votes where post_votes.post_id = posts.id) AS nbvotes'))
                 ->orderBy('nbvotes',$order));
  });
  // apply same logic for favorites
  // if the orderBy is neither favorites or votes, by name or email for example...
  $query->when($orderBy != 'favorites' && $orderBy != 'votes', function ($query) use ($orderBy,$order) {
    return $query->orderBy($orderBy,$order);
  });
  // executing the query
  $posts = $query->get();