简体   繁体   中英

Laravel Eager Loading a Relation with Eloquent

I'm attempting to load all of the items in my Lists database, while applying optional filters if they're specified. With these, I'd like to load the count of subscribers for each of the lists. I can do this via the normal $list->subscribers()->count() call within the foreach loop in the view, but can I do this through the actual pagination function?

Inside of my ListsRepo.php file:

<?php namespace Acme\Repos;

    use Lists;

    class DbListsRepo implements ListsRepoInterface {

        public function getPaginated(array $params)
        {
            $list = new Lists;

            // See if there are any search results that need to be accounted for
            if ($params['search'] != null) $list = $list->where('name', 'LIKE', "%".$params['search']."%");

            // See if we need to restrict the results to a single user
            if ($params['user'] != null) $list = $list->where('userID', $params['user']);

            // Check if the data should be sorted
            if ($this->isSortable($params)) $list = $list->orderBy($params['sortBy'], $params['direction']);

            return $list->paginate(10);
        }

        public function isSortable(array $params)
        {
            return $params['sortBy'] and $params['direction'];
        }

    }

Inside of my index.blade.php file:

....
@if ($lists->count())
    @foreach ($lists as $list)
        <tr>
            <td><h4>{{ $list->name }}</h4></td>
            <td><p>{{ $list->subscribers()->count() }}</p></td>
        </tr>
    @endforeach
@endif
...

So is there a way to properly attach the subscribers count to my getPaginated function? The current implementation results in an N+1 scenario.

You should be able to do it by including the eager-load in your getPaginated function:

public function getPaginated(array $params) {  
     $list = Lists::newQuery();

    // See if there are any search results that need to be accounted for
    if ($params['search'] != null) $list->where('name', 'LIKE', "%".$params['search']."%");

    // See if we need to restrict the results to a single user
    if ($params['user'] != null) $list->where('userID', $params['user']);

    // Check if the data should be sorted
    if ($this->isSortable($params)) $list->orderBy($params['sortBy'], $params['direction']);

    $list->with('subscribers');

    return $list->paginate(10);
}

And then in your blade you can simply do count($list->subscribers) because the subscribers will be preloaded into your list models.

You have to use PHP's count() on the results array, not SQL's COUNT when it comes to eager loading, as eager loading is done with a single select statement on the related table.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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