简体   繁体   English

如何在不使用foreach的情况下通过Laravel Eloquent模型中的3加入查询

[英]How to have query by 3 join in Laravel Eloquent model without foreach

Is there anyway to remove to foreach from this code? 无论如何,要从此代码中删除foreach吗?

    $user = \Auth::user();
    foreach ($user->categories as $category) {
        $channels[] = $category->channel();
    }
    return $channels;

I want to use the paginate function but it's not possible with the foreach ! 我想使用分页功能,但是foreach不可能的!

Eloquent does not perform JOIN queries, if you actually need a JOIN, you'll need to drop down to the query builder and write the query your self. Eloquent不执行JOIN查询,如果您确实需要JOIN,则需要下拉至查询构建器并编写自己的查询。

If, however, you're simply trying to avoid the N+1 problem, the you should use eager loading. 但是,如果您只是想避免N + 1问题,则应使用预先加载。 This will create 1 additional WHERE foreign_id IN(...) query per relationship type. 每个关系类型将创建1个额外的WHERE foreign_id IN(...)查询。 So in total there would be: 因此总共会有:

  • 1 query to fetch the user record 1查询以获取用户记录
  • 1 query to fetch all categories that belong to the user 1个查询以获取属于该用户的所有类别
  • 1 query to fetch all channels that belong to any of the previously fetched categories 1个查询以获取属于先前获取的任何类别的所有频道

Since you already have the user instance in memory, you can avoid re-fetching the user record via lazy eager loading . 由于您已经在内存中存储了用户实例,因此可以避免通过延迟加载而重新获取用户记录。

Laravel paginator documentation is a little short, especially with creating/paginating manually like you will have to do .... here is a brief overview of how they work how to make them work... Laravel分页器文档有些简短,尤其是像您必须手动创建/分页一样。...这里是它们如何工作的简要概述,以及如何使其工作...

No magic, paginators will call your controller function for every page. 没什么大不了的,分页器会在每一页上调用您的控制器函数。 The request will have the pagination information in it. 该请求中将包含分页信息。 It is your job to actually select and slice the page. 实际选择并切片页面是您的工作。 The paginator simply presents it... which is a big part of the work... 分页器只是呈现它...这是工作的重要部分...

Your $channels[] array will have to be sliced and returned properly... something like this... 您的$ channels []数组将必须被切片并正确返回...像这样...

public function channels(){

    // we have to build the paginator ourselves, your result is an array...
    $user = \Auth::user();
    foreach ($user->categories as $category) {
        $channels[] = $category->channel();
    }

    // this basically gets the request's page variable...This is how pagination works under the hood... we defaults to 1
    $page = Paginator::resolveCurrentPage('page') ?: 1;

    // Assume 15 items per page... so start index to slice our array
    $startIndex = ($page - 1) * 15;

    // Length aware paginator needs a total count of items... to paginate properly
    $total = count($channels);

    // Eliminate the non relevant items... We have to slice the array ourselves...
    $results = array_slice($channels, $startIndex, 15);

    $paginatedChannels =  new LengthAwarePaginator($results, $total, 15, $page, [
        'path' => Paginator::resolveCurrentPath(),
        'pageName' => 'page',
    ]);
    return view('yourViews', compact('paginatedChannels'));
}

The key is you have to prepare the data slice yourself... 关键是您必须自己准备数据切片...

You can post your data structure so we can come up with a better alternative to the query itself... but this should work if that $category->channel() function works... 您可以发布数据结构,以便我们为查询本身提供更好的选择...但是,如果$ category-> channel()函数有效,则此方法应该有效...

What about this way? 那这样呢

$categories = \Auth::user()->categories()->pluck('id')->toArray();
return \App\Channel::wherein('category_id', $categories)->paginate();

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM